A
Another_eYes
Unregistered / Unconfirmed
GUEST, unregistred user!
做了一个dll: TestDll, exports了三个函数:
function func1: THandle;
stdcall;
function func2(handle: THandle): boolean;
stdcall;
function func3(handle: THandle): boolean;
stdcall;
在这个dll中定义了一个类:
TMyClass = class(TComponent)
public
str: string;
......
end;
function func1: THandle;
begin
result := integer(pointer(TMyClass.Create(Application)));
end;
function func3(handle: THandle): boolean;
begin
result := false;
if handle = 0 then
exit;
TMyClass(TObject(ptr(handle))).Free;
result := true;
end;
function fun2(handle: THandle): boolean;
var
myclass: TMyClass;
begin
result := false;
if handle = 0 then
exit;
myclass := TMyClass(TObject(ptr(handle)));
with myclassdo
begin
str := 'Test String';
......
end;
result := true;
end;
另做了个form调用这个dll, form上只有一个button.
button.Onclick:
var
f1, f2: integer;
func1: function : Integer;
stdcall;
func2: function (handle: Integer): boolean;
stdcall;
func3: function (handle: Integer): boolean;
stdcall;
begin
f1 := loadlibrary('TestDll.dll');
if f1 <> 0 then
begin
@func1 := GetProcAddress(f1, 'func1');
@func2 := GetProcAddress(f1, 'func2');
@func3 := GetProcAddress(f1, 'func3');
f2 := func1;
func2(f1);
// 当时不小心写错了, 应该传入f2的
........... // 释放....
end;
end;
两个程序分别编译通过.
在调试testdll时一个有趣的现象发生了:
function fun2(handle: THandle): boolean;
var
myclass: TMyClass;
begin
result := false;
<---断点在此, 开始单步运行
if handle = 0 then
exit;
myclass := TMyClass(TObject(ptr(handle)));
<----此步无法跟踪, 直接跳过了,
断点设在这里的话重新编译时编译器说是无效断点, 被优化掉了.
with myclassdo
begin
str := 'Test String';
<------ 这里出错, 访问冲突
......
end;
result := true;
end;
后来发觉是主程序中写错了, 改正之后, dll中不管断点设在哪句编译器都认为正确.
现在的问题是:
在dll编译过程中它怎么知道调用者的参数是错的?
为什么会把 myclass := TMyClass(TObject(ptr(handle)));
这句上的
断点优化掉????
它怎么知道这句是无效的??????
当我改正主程序之后它又是怎么知道调用者的参数是正确的, 又认为这句有效, 允许设置
断点?(主程序是单独编译的呀? 而且加载dll用的是动态加载和释放)
有点见鬼了的感觉.
function func1: THandle;
stdcall;
function func2(handle: THandle): boolean;
stdcall;
function func3(handle: THandle): boolean;
stdcall;
在这个dll中定义了一个类:
TMyClass = class(TComponent)
public
str: string;
......
end;
function func1: THandle;
begin
result := integer(pointer(TMyClass.Create(Application)));
end;
function func3(handle: THandle): boolean;
begin
result := false;
if handle = 0 then
exit;
TMyClass(TObject(ptr(handle))).Free;
result := true;
end;
function fun2(handle: THandle): boolean;
var
myclass: TMyClass;
begin
result := false;
if handle = 0 then
exit;
myclass := TMyClass(TObject(ptr(handle)));
with myclassdo
begin
str := 'Test String';
......
end;
result := true;
end;
另做了个form调用这个dll, form上只有一个button.
button.Onclick:
var
f1, f2: integer;
func1: function : Integer;
stdcall;
func2: function (handle: Integer): boolean;
stdcall;
func3: function (handle: Integer): boolean;
stdcall;
begin
f1 := loadlibrary('TestDll.dll');
if f1 <> 0 then
begin
@func1 := GetProcAddress(f1, 'func1');
@func2 := GetProcAddress(f1, 'func2');
@func3 := GetProcAddress(f1, 'func3');
f2 := func1;
func2(f1);
// 当时不小心写错了, 应该传入f2的
........... // 释放....
end;
end;
两个程序分别编译通过.
在调试testdll时一个有趣的现象发生了:
function fun2(handle: THandle): boolean;
var
myclass: TMyClass;
begin
result := false;
<---断点在此, 开始单步运行
if handle = 0 then
exit;
myclass := TMyClass(TObject(ptr(handle)));
<----此步无法跟踪, 直接跳过了,
断点设在这里的话重新编译时编译器说是无效断点, 被优化掉了.
with myclassdo
begin
str := 'Test String';
<------ 这里出错, 访问冲突
......
end;
result := true;
end;
后来发觉是主程序中写错了, 改正之后, dll中不管断点设在哪句编译器都认为正确.
现在的问题是:
在dll编译过程中它怎么知道调用者的参数是错的?
为什么会把 myclass := TMyClass(TObject(ptr(handle)));
这句上的
断点优化掉????
它怎么知道这句是无效的??????
当我改正主程序之后它又是怎么知道调用者的参数是正确的, 又认为这句有效, 允许设置
断点?(主程序是单独编译的呀? 而且加载dll用的是动态加载和释放)
有点见鬼了的感觉.