关于DLL的问题(急)(100分)

  • 主题发起人 主题发起人 robinswp
  • 开始时间 开始时间
R

robinswp

Unregistered / Unconfirmed
GUEST, unregistred user!
我在Delphi 5 中调用VC的动态连接库,在测试程序中,没有错.但在另一个程序中调用,
就会出现地址非法访问.请问各位这是什么问题.
 
莫名其妙,你不能说清楚些吗?
 
我用delphi写了两个程序调用调用VC写的DLL,第一个没有出现错误,在第二个程序中,出现
"Access Violation at address 00F72064 in module 'XXX.dll',write of address
00FE320c".
 
我的意思是你把使用的代码等等写出来,才能判断是DLL有问题还是你的程序
有问题。
 
DLL用数据库了吗?若用了.就是这个原因了.
我不会VC.但书上说应该注意调用时,DELPHI是Register,
VC不是.应该用Stdcall.
 
源程序如下:
TSendData = function(Dest,Sour:PChar;datatype:Smallint;s_sub,r_sub:PChar;tlen:integer;text:PChar;wait:integer;TradeSour,DistCode,MainTx,TermNo,OperNo,Id:PChar):smallint;stdcall;//far;External 'mgbdll.dll';
TRecvData = function(Dest,Sour:PChar;var datatype:Smallint;s_sub,r_sub:PChar;var tlen:integer;text:Pchar;wait:integer;DataNum,MainTx,ReturnNo:PChar):smallint;stdcall;//far;External 'mgbdll.dll';
...
len:=10;
SendSub:=SendSub+1;
GetMem(GetTxt,4050);
GetMem(Num,20);
GetMem(MTx,20);
GetMem(RetNo,20);
GetMem(IpDest,20);
GetMem(IpSource,20);
GetMem(PSendSub,20);
GetMem(PRecvSub,20);
IpDest:='10.1.1.169';
IpSource:='10.1.1.180';
PSendSub:='TrainServer';
PRecvSub:=Pchar(IntToStr(SendSub));
DType:=0;
SendTxt:=SendTxt+'|^';
Handle:=LoadLibrary('mgbdll.dll');
if Handle <> 0 then
begin
@SendData:=GetProcAddress(Handle,'SendData');
if @SendData <> nil then
Ret:=SendData(IpDest,IpSource,DType,PSendSub,PRecvSub,len,Pchar(SendTxt),
6000,'M','11111',Pchar(CMainTx),'111',Pchar(CurrentOperCode),Pchar(CurrentCustNo));
//sleep(3000);
@RecvData:=GetProcAddress(Handle,'RecvData');
if @RecvData <> nil then
Ret:=RecvData((IpSource,IpDest,DType,PSendSub,PRecvSub,len,GetTxt,6000,Num,MTx,RetNo);
end;
FreeLibrary(Handle);

我敢肯定dll在执行到RecvData函数中下面两句时出错:

datatype = aMSG.datatype;
strcpy(s_sub, aMSG.s_sub);

Dll中函数:
short __stdcall RecvData(char *Dest,char *Sour,short datatype,
char *s_sub, char *r_sub, int tlen, unsigned char *text, int wait,
char * DataNum,char *MainTx,char *ReturnNo)
short __stdcall SendData(char *Dest,char *Sour,short datatype,
char *s_sub, char *r_sub, int tlen,
unsigned char *text, int wait,
char *TradeSour, char *DistCode, char *MainTx,
char *TermNo, char * OperNo, char * ID)

 
我认为这一句是根源:

PRecvSub:=Pchar(IntToStr(SendSub))


IntToStr产生临时对象,

所以。。。

我想你应该明白了
 
还有,那些对指针的赋制,很奇怪,对应与C中,你的代码就成了:

char * p = new char[20];

p = "asdasda";

有可能越界。

 
Delphi和VC对DLL的参数调用各有规定,你可以用Windows的工具查看一下,
是否参数引用对不对。安全声明和调用为Stdcall比较好。特别是字节对齐的问题,你可
以在Delphi中设置为Byte对齐,不要用Dword对齐。这在菜单Object设置。
 
to hustmouse:
能不能讲的详细一点.为什么IntToStr会产生临时对象?那么我该如何实现它,另外指针我该如何
赋值?
to hsj:
"在Delphi中设置为Byte对齐,不要用Dword对齐。这在菜单Object设置。" 我这么也找不到.
 
参数好象没有什么对齐的问题

看下面的代码:

var p:Pchar;
x:pchar;
begin
p := pchar(IntToStr(190))
// 1
x := pchar(IntToStr(200))
// 2
Edit1.text := string(p)
// 3
end;

如果没有语句2,则3执行的显示结果是正确的
但一旦加上了语句2,则3显示的就不正确了。

IntToStr产生的string对象是临时的,在作为右值使用后,其值(或内存)

无效,但如果没有其他的东西冲掉它的话,它还存在,这就是在没有语句2时

显示正确的原因。

在加了语句2 后,堆栈被改变(那个临时对象应该建立在堆栈上),所以
就显示不正确了。


 
Delphi好久没用了,关于内存拷贝的函数忘了,不过,我可以用Windows API来写,

var p,p1:pchar;
s,s1:string;

GetMem( p,300 );
GetMem( p1,20);

s := inttostr( 200 );

CopyMemory( p,PChar(s),length(s));

s1 := '123123';

CopyMemory( p1,PChar(s1),length(s1));
 
问题好像没那么复杂吧:
你的DLL中有 short datatype参数,
为什么delphi要声明为 var datatype:smallint;呢?

short datatype是传值,而var datatype:smallint是传指针,不匹配呀,
如果是short* datatype,才应该用var datatype:smallint;

别的代码我没看,但这一点恐怕肯定有问题吧。
 
我更怀疑没有加载 ShareMEM

我以前写的 DLL 不加载 ShareMEM 时很不稳定,有时对,有时错!
 
问题解决了.
真如hustmouse所说的:我的指针赋值有问题.不能给指针直接赋值,必须用StrCopy、
Strpcopy等赋值。否则前面的GetMem就没用了。
好了,该瓜分了。可能分配不均,希望各位不要介意。当然有意见也无效。
 
多人接受答案了。
 
后退
顶部