调用动态库后,句柄 及 类的私有成员变量为什么会变???

kampan 2008-08-27 11:50:21
大侠们给看看:


TfrmA = class(TfrmB)
btnSet: TBitBtn;
private
I: Integer;
public
procedure Test;
end;

procedure TfrmATest;
var
Handle1, Handle2: THandle;
begin
XHandle := Self.Hanlde;
I := 1;
if I = 1 then
GetX() //GetX为动态库函数
Handle2 := Self.Handle;
else
....;

调用之后:
此时 I 已经不为1了,而是一个很大的负数
Handle1与Handle也不相等,为什么?

end;



...全文
105 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
kampan 2008-08-30
  • 打赏
  • 举报
回复
我用改过测试的结果同样如此 I := -1982713088;当然动态库函数我还没改成int AnalyseGetData(char *sParam,int iParamLen,char *sDataFormat,char *sBack )形式 ,我没有源码。等拿到源码我再试试。

十分感谢lake_cx !如果需要,可能还找你讨论。


kampan 2008-08-29
  • 打赏
  • 举报
回复
只差lake_cx 最后确认的一步,怎么看不到人了呢
lake_cx 2008-08-29
  • 打赏
  • 举报
回复
按照你说的,应该就是这么调用,我还以为你试过了没问题呢(有问题早就说出来了。。。)
PS:LoadLibrary中用相对路径不保险;貌似ReturnChar中的iLen是多于的,string中第一个字节就是它的长度
kampan 2008-08-28
  • 打赏
  • 举报
回复
谢谢lake_cx,根据你的意思,我做了如下调整,请指正。

type
TAnalyseGetData = function(sParam:pchar;iParamLen:integer;sDataFormat:pchar;var sBack:pchar): integer;stdcall;

function AnalyseGetData(sParam:pchar;iParamLen:integer;sDataFormat:pchar): ReturnChar ;
var
iBack:integer;
th:Thandle;
anaData:TAnalyseGetData;
tp:TFarProc;
reChar:ReturnChar;
i : integer;
sBack : pchar;
begin
iBack := 0;
th := LoadLibrary('.\645_1997.dll');
if (th > 0) then
begin
try
tp := GetProcAddress(th,'AnalyseGetData');
if (tp <> nil) then
begin
anaData := TAnalyseGetData(tp);
//getMem(sBack,sizeof(pchar)); 去掉分配内存
iBack := anaData(sParam,iParamLen,sDataFormat,sBack);
reChar.iLen := iBack;
if iBack > 0 then
reChar.sBack := sBack; //直接赋值
end //if (tp <> nil) then
else
begin
iback := 0;
reChar.iLen := iBack;
reChar.sBack := '';
end;
finally
FreeLibrary(th);
end;//try
end;//if (th > 0) then
result := reChar;
end;


调用:
rec := AnalyseGetData(pchar(sBuffer),
4,
pchar(node.strings[6]));
lake_cx 2008-08-28
  • 打赏
  • 举报
回复
这个定义本身就是不对的(怎么没写WINAPI?最后一个参数应该是char *sBack才正确)
int AnalyseGetData(char *sParam,int iParamLen,char *sDataFormat,char *&sBack)
最后一个参数是返回一个char *,而不是传入一个char *让AnalyseGetData为其填充字符串
因此对应的调用规范应该是
function AnalyseGetData(sParam:pchar;iParamLen:integer;sDataFormat:pchar;var sBack:pchar): integer;stdcall;
因此你只要申明一个PChar指针就可以了,AnalyseGetData会为字符串开辟一段内存,并写好数据,然后把地址写到你这个PChar指针中去,因此字符串数据是无法释放的,会导致内存泄露
kampan 2008-08-28
  • 打赏
  • 举报
回复
首先非常感谢lake_cx 耐心的看完代码,并提出多个疑问!其次要说明一下,这是我刚刚接手主管的一个程序,动态库内部实现我不知道,没有源码。

其它待我逐一回答:

1、ReturnChar的类型是什么?
记录类型
type
ReturnChar = record
iLen : integer;
sBack: string;
end;


2、两个sBack,编译能通过?
没看到两个,编译无问题。 若你是指reChar.sBack := reChar.sBack + sBack[i]; 请看问题1

3、getMem(sBack,sizeof(pchar));字符串只要四个字节就够了?
此处似乎有待斟酌,我再仔细看看

4、645_1997.dll中AnalyseGetData方法的实现或者调用规范是什么?
无源码,
C++声明为:
函数定义 int AnalyseGetData(char *sParam,int iParamLen,char *sDataFormat,char *&sBack )
函数用途 解析查询返回的报文
参数 sParam:[输入量],查询返回的报文
iParamLen:[输入量],报文长度
sDataForamt:[输入量],数据格式
sBack:[输出量],输出解析报文
返回值 int,解析后的报文长度


5、for i := 0 to iBack -1 do reChar.sBack := reChar.sBack + sBack[i];用不着这么写
直接这么写?reChar.sBack := sBack

6、代码你可以重写了。。。
别人都用了很长时间了,最后考虑。
lake_cx 2008-08-28
  • 打赏
  • 举报
回复
1、ReturnChar的类型是什么?
2、两个sBack,编译能通过?
3、getMem(sBack,sizeof(pchar));字符串只要四个字节就够了?
4、645_1997.dll中AnalyseGetData方法的实现或者调用规范是什么?
5、for i := 0 to iBack -1 do reChar.sBack := reChar.sBack + sBack[i];用不着这么写
6、代码你可以重写了。。。
kampan 2008-08-28
  • 打赏
  • 举报
回复
我写的GetX实际为下面的AnalyseGetData ,它把动态库中的函数又封装了一下,如下所示:

type
TAnalyseGetData = function(sParam:pchar;iParamLen:integer;sDataFormat:pchar;sBack:pchar): integer;stdcall;

function AnalyseGetData(sParam:pchar;iParamLen:integer;sDataFormat:pchar): ReturnChar ;
var
iBack:integer;
th:Thandle;
anaData:TAnalyseGetData;
tp:TFarProc;
reChar:ReturnChar;
i : integer;
sBack : pchar;
begin
iBack := 0;
th := LoadLibrary('.\645_1997.dll');
if (th > 0) then
begin
try
tp := GetProcAddress(th,'AnalyseGetData');
if (tp <> nil) then
begin
anaData := TAnalyseGetData(tp);
getMem(sBack,sizeof(pchar));
iBack := anaData(sParam,iParamLen,sDataFormat,@sBack);
reChar.iLen := iBack;
if iBack > 0 then
for i := 0 to iBack -1 do
reChar.sBack := reChar.sBack + sBack[i];
//FreeMem(@sBack);
end //if (tp <> nil) then
else
begin
iback := 0;
reChar.iLen := iBack;
reChar.sBack := '';
end;
finally
FreeLibrary(th);
end;//try
end;//if (th > 0) then
result := reChar;
end;


调用:
rec := AnalyseGetData(pchar(sBuffer),
4,
pchar(node.strings[6]));
lake_cx 2008-08-28
  • 打赏
  • 举报
回复
你什么都不说,谁能给你搞定啊

把DLL中GetX的实现或者调用规范的文档贴出来啊
kampan 2008-08-28
  • 打赏
  • 举报
回复
一夜过去了,没有人说出个123啊?!
kampan 2008-08-27
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 akirya 的回复:]
呃通常是动态库中的函数越界造成的

你先把GetX都删除再调用试试看.
[/Quote]

删掉肯定没问题,我就是想知道此种情况下(调用动态库),怎样处理?
  • 打赏
  • 举报
回复
呃通常是动态库中的函数越界造成的

你先把GetX都删除再调用试试看.
kampan 2008-08-27
  • 打赏
  • 举报
回复
function GetX(sParam:pchar;iParamLen:integer;sDataFormat:pchar;sBack:pchar): integer;stdcall;
kampan 2008-08-27
  • 打赏
  • 举报
回复
GetX是动态载入,所传的参数应该没有问题。
lake_cx 2008-08-27
  • 打赏
  • 举报
回复
看一下GetX的调用规则或参数表对不对
看起来像是堆栈中的Self指针被破坏了

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧