【问题标题】:Calling library function eats up the stack. Why?调用库函数会占用堆栈。为什么?
【发布时间】:2013-09-07 21:10:44
【问题描述】:

对不起,这对 Delphi 程序员来说可能也很容易,但对我来说不是。我有一个我正在调用的库函数,基本上它吃掉了我的堆栈。它通过将函数的变量推入堆栈来做到这一点,但不知何故,Delphi 不会将它们从堆栈中弹出。所以在函数结束后,我无处可去。有趣的是,我只要有参数就可以做“pop eax”,而且它可以工作。任何人都可以阐明发生了什么吗? 工作代码如下:

function LoadIntoMemory(sdiPath: String): Integer;
var
   retValue: Integer;
begin
  retValue := file_open(PAnsichar(AnsiString(sdiPath)), @filedata, @filedatasize);
   asm
     pop eax
     pop eax
     pop eax
   end;
 end;

如前所述,不从堆栈中弹出它就会崩溃。

函数本身来自一个 C DLL,静态链接如下:

function file_open (filename: PAnsichar; filedata: PPAnsichar; filedatasize: PLongInt): Integer; stdcall; external  'libLib';

动态链接不会改变行为。

【问题讨论】:

  • 我会尝试“cdecl”。不确定它会有所帮助,因为变量的顺序会改变。

标签: delphi crash stack delphi-xe3


【解决方案1】:

好的,我现在有了。抱歉,可能是简单的 RTFM 问题。我应该使用 cdecl;而不是标准调用。只希望所有这些 Delphi DLL 链接教程都能在某处提到它。

http://docwiki.embarcadero.com/RADStudio/XE4/en/Procedures_and_Functions

【讨论】:

    【解决方案2】:

    这是一个调用约定不匹配。被调用者是 cdecl,调用者使用 stdcall。关键区别在于谁清理堆栈。对于 stdcall 它是被调用者,对于 cdecl 它是调用者。

    这解释了您观察到的情况。实际功能是 cdecl。所以不会清理堆栈。但是您的调用代码认为该函数是 stdcall ,因此希望被调用者清理堆栈。因此,双方都没有清理它。

    更多详情:http://en.m.wikipedia.org/wiki/X86_calling_conventions

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-07
      • 1970-01-01
      • 1970-01-01
      • 2021-05-10
      • 2015-08-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多