调用DLL出现非法操作!版主进来看看吧! (100分)

  • 主题发起人 主题发起人 iCANK
  • 开始时间 开始时间
I

iCANK

Unregistered / Unconfirmed
GUEST, unregistred user!
一个procedure,写在程序内部很好,没有任何问题。但把他写在DLL里,调用一次可以,
调用第二次就出现非法操作,报访问地址错误:
Access violation at address 00403004 in module 'TEST.EXE'. Read of address FFFFFFFF.
这是一个向主程序的StringGrid写数据的procedure。
 
有没有资源释放啊?
 
调用代码:用断点调试,FreeLibrary(HInst);已经被执行。

type
TCalRLWater = procedure (Sender: TAdvStringGrid; RecordCount: Integer; ResultACol: Integer); stdcall;
......
......
HInst:=LoadLibrary('Round.DLL');
if HInst>0 then
try
FPointer:=GetProcAddress(Hinst,Pchar('CalRLWater'));
if FPointer<>nil then
begin
MyTest:=TCalRLWater(FPointer);
Try
MyTest(asg,RecordCount,1);
except on E:Exception do
ShowMessage(E.Message);
end;
end
else
ShowMessage('DLL procedure not found!');
finally
FreeLibrary(HInst);
end
else
ShowMessage('Library not found!');
 
还有,怎么样调试DLL啊?按F7就不去啊!
 
在 Run -> Parameters 菜单中设置调用 DLL 的主程序,然后运行即可调试 DLL。
 
有没有把主程序的 Application 对像指针传递给 DLL ?
 
你能保证两个地方的 TAdvStringGrid 是同一个实例?
这种算法有严重的问题。
 
DLL 中传递类是一个非常危险而往往最是无效和麻烦的事!
如果真要这样,传递句柄!并且用var(in|out) 作传递。
 
>> DLL 中传递类是一个非常危险而往往最是无效和麻烦的事!
>> 如果真要这样,传递句柄!并且用var(in|out) 作传递。
能解释一下为什么吗?谢谢!
 
dll中CalRLWater怎么写的?贴
 
DLL Code:

library Round;

{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }

uses
Forms, SysUtils, Classes, Grids, BaseGrid, AdvGrid;

{$R *.RES}

procedure CalRLWater(Sender: TAdvStringGrid; RecordCount: Integer; ResultACol: Integer); stdcall;
begin
if (Sender.Cells[ResultACol,1] = '.') and (Sender.Cells[ResultACol,RecordCount] = '..') then
begin
Sender.Cells[ResultACol,1] := '左水边';
Sender.Cells[ResultACol,RecordCount] := '右水边';
end
else if (Sender.Cells[ResultACol,1] = '..') and (Sender.Cells[ResultACol,RecordCount] = '.') then
begin
Sender.Cells[ResultACol,1] := '右水边';
Sender.Cells[ResultACol,RecordCount] := '左水边';
end
else
begin
Application.MessageBox('error','error',16);
end;
end;

exports
CalRLWater;

begin
end.

这个Round.dll里还有很多类似的程序,都是向TAdvStringGrid写数据的procedure,为了单
个测试,主程序中只调用了CalRLWater。
 
这种算法有严重的问题!!
那要实现这种程序,要怎么做呢?
程序是这样的:
主程序中有个TAdvStringGrid,名为asg。读取数据库中的字段,把数据写到TAdvStringGrid
里面,然后对数据进行计算,计算是一列一列计算,比如,第1行第3列的数字 和 第1行第6列
的数字 相加后除以 第1行第7列的数字,结果放在第1行第9列,然后,行循环。而且,计算是
有顺序的,比如,要有了第10列的数据,才能计算第12列的数字……(怕说不清楚,罗嗦了。
:P)
这种计算可能会因为用户的不同而改变,所以,我要把计算的部分单独放到DLL里面,不同的用
户,发放不同的DLL就好了。
应该怎么做呢?请大虾们指教!
给个源码或网址都好,拜托拜托!
 
ddev:
DLL 中传递类是一个非常危险而往往最是无效和麻烦的事!
如果真要这样,传递句柄!并且用var(in|out) 作传递。
应该怎么做啊?请指教。
谢谢!!!
 
不,你这样传递没问题,只是个指针而已,有什么问题我再想想
 
调用 Sender.Cells[Col, Row] 时有没有超出 ColCount 或 RowCount ?
 
没有,说了,写在程序里没有问题,但把他写到DLL里就有问题了。
程序本身是对的。
下个星期就要用,各位大虾,拜托拜托!!
 
是了,你没必要不停的 LoadLibrary 、 FreeLibrary 吧
你改成开始 LoadLibrary 一次、 最后 FreeLibrary 一次可能就不出错了
 
或者干脆只loadlibrary一次,以后不freelibrary也没关系,最后windows会freelibrary它的
不会造成什么内存的损失
 
还是不行啊。我把其它的precedure都注释掉,是留下这个了。还是出现同样的错误!
急死我了!!!!

:(
 
Uses ShareMem 为你的DLL的第一个引用单元,请试一试,谢谢!
 
后退
顶部