3

抱歉,这对 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';

动态链接不会改变行为。

4

2 回答 2

3

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

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

于 2013-09-07T21:30:09.780 回答
0

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

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

更多细节在这里:http ://en.m.wikipedia.org/wiki/X86_calling_conventions

于 2013-09-08T17:38:01.627 回答