【问题标题】:Symbol eliminated by linker (Delphi)链接器消除的符号(Delphi)
【发布时间】:2010-09-27 22:15:19
【问题描述】:

帮助! 在我的 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 调试器对其进行测试。
  • ` 表明符号已从链接器中删除`:这不是来自 Delphi IDE 的实际消息,是吗?请提供实际的错误消息,而不是您对错误消息的解释。

标签: c delphi dll external


【解决方案1】:
  1. 在调用外部函数之前设置断点(不是外部声明上的断点)。
  2. 打开调试器反汇编窗口。 (我忘记了到达那里的确切菜单路径)
  3. 一次执行一个机器指令。您不需要了解所有这些(尽管它不会造成伤害),但请密切注意跳转和呼叫指令。
  4. 随着代码设置调用参数,然后是调用指令,会出现一些问题。
  5. 遵循(步入)调用指令。由于这是一个外部调用,预计会看到跳转间接指令。
  6. 跟随跳转到目的地。您现在应该在 C++ DLL 中。如果您在 CBuilder 中使用调试信息构建 DLL,那么您应该也有符号信息和源代码行信息。

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

【讨论】:

  • +1 获取有关如何诊断问题所在的秘诀
【解决方案2】:

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

我的解决方案,当它过去发生在我身上时,通常是在 initialization 部分中对有问题的例程进行无意义的调用。 smartlinker 不会弄乱这些。你能做到这一点而不会导致任何错误吗?

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

【讨论】:

  • Mason,谢谢你的回复,我在初始化部分试过了,收到运行时错误。链接器看到函数,却不识别参数....很奇怪。
  • 我记得 Danny Thorpe 的神奇触摸方法:procedure Touch(var arg); begin end;,它胜过编译器和链接器。
  • @Dennis:嗯。如果“触摸”外部过程改变了行为,请仔细查看您调用外部过程的上下文。链接器认为程序没有使用您的调用,这意味着程序没有使用包含调用的代码主体。这可能是链接器错误。需要检查和报告,因为神奇地消失的东西有回来的坏习惯。
  • 感谢 dthorpe 的提醒。这几行代码已经很久没有修改过了。我真的不明白它怎么会像那样弹出。该函数是对 dll 的外部调用,因此程序的代码主体是现存的。以前从来没有遇到过这个。与仅删除参数的链接器相比,未解析的符号更容易理解。
【解决方案3】:

注意 BOOL 和 Boolean 是不同的。 BOOL 在 Windows.pas 中定义为

type
  BOOL = LongBool;

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

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

【讨论】:

  • 这不应该是评论而不是答案吗?
猜你喜欢
  • 2014-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多