链接器消除的符号(Delphi)

3

帮忙!在我的Delphi 4应用程序中查看入站函数参数内容时,出现了以下错误。

代码调用dll中的一个函数,该函数有3个参数(app.handle, pchar, boolean)

声明函数在externs.pas中声明为:

function AdjustVoucherDifference(hOwner :HWnd; Receipt_ID :PChar; 
  bCommit: Boolean): boolean; stdcall; 
  external 'FBCoupon.dll' name 'AdjustVoucherDifference';

在另一个源文件中,代码将其称为:

AdjustVoucherDifference(Application.Handle, PChar(Receipt_ID), true);

在调试模式下,我可以看到源文件中的有效值,但当它在externs.pas的行上中断时,值的工具提示(或CTRL+F7)显示符号已从链接器中删除,并且当执行位于dll中时,我收到异常。

DLL是使用CBuilder4开发的,特定函数声明为:

BOOL __stdcall __DLLTYPE__ AdjustVoucherDifference(HWND hOwner, 
  char *receipt_id, bool commit);

编译器优化被关闭。
谢谢!

你正在指责链接器“删除”符号,导致dll函数内部异常。在您能够证明函数未收到正确参数之前,我不确定这一点。如果您控制dll,只需使用构建器将主机应用程序设置为Delphi进行调试。如果没有,也许您可以使用Delphi创建一个带有此名称和公司的函数的虚拟dll,并使用Delphi调试器进行测试。 - jachguate
“显示符号已从链接器中删除”:这不是 Delphi IDE 的实际消息,对吗?请提供实际的错误消息,而不是您对错误消息的解释。 - Cosmin Prund
3个回答

4
  1. 在调用外部函数之前设置断点(不是在外部声明上设置断点)。
  2. 打开调试器反汇编窗口。(我忘记了具体的菜单路径)
  3. 逐步执行机器指令。您不需要理解所有指令(虽然这并没有坏处),但要密切注意跳转和调用指令。
  4. 当代码为调用设置参数时,会有一些杂音,然后是一个调用指令。
  5. 跟随(步入)调用指令。由于这是一个外部调用,所以预计会看到一个跳转间接指令。
  6. 跟随该跳转到达其目的地。现在,您应该在C++ DLL内部。如果您使用带有调试信息的CBuilder构建了DLL,则还应该具有符号信息和源代码行信息。

如果Delphi端的参数声明与C++端的期望不匹配,则应开始看到在调用的C++端出现问题,这可能导致访问冲突异常或由C ++ dll生成的运行时错误。


1
+1 是为了教你如何诊断问题的配方。 - Marjan Venema

1
请注意,BOOL 和Boolean 是不同的。BOOL在Windows.pas中定义为:
type
  BOOL = LongBool;

所以 SizeOf(BOOL) = 4,而 SizeOf(Boolean) = 1

即使它不能帮助您解决问题,在 Delphi 声明中将 Boolean 替换为 BOOL(或 LongBool)以使声明正确。


1
这不应该是一条评论吗,而不是一个答案? - mg30rg

1

连接器不受编译器优化的影响。连接器将“智能链接”掉任何它可以证明在程序中永远不会被调用的例程。不幸的是,这意味着调试器无法调用它。

当这种情况发生在我身上时,我的解决方案通常是在初始化部分中放置一个对此例程无关紧要的调用。智能链接器不会处理这些内容。您能在不引起任何错误的情况下做到这一点吗?

initialization
  AdjustVoucherDifference(0, '', true); //DO NOT SMARTLINK THIS OUT!
end;

Mason,谢谢你的回复,我在初始化部分尝试了一下,但是收到了运行时错误。链接器看到了这个函数,但是没有识别参数...非常奇怪。 - Dennis
3
我记得Danny Thorpe的神奇Touch方法:procedure Touch(var arg); begin end;,它能够智胜编译器和链接器。 - Jeroen Wiert Pluimers
@Dennis:嗯。如果“触碰”外部过程会改变行为,请仔细查看调用外部过程的上下文。链接器认为您的调用未被程序使用,这意味着包含调用的代码体也未被程序使用。这可能是链接器的错误。需要进行检查和报告,因为神奇地消失的东西往往会不请自来。 - dthorpe
感谢dthorpe的提醒。这些代码已经很长时间没有修改了。我真的不明白它怎么会突然出现。这个函数是对dll的外部调用,所以代码体存在于程序中。以前从未遇到过这种情况。未解决的符号比链接器丢失参数更容易理解。 - Dennis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接