调用库函数会占用堆栈。为什么?

时间:2013-09-07 21:10:45

标签: delphi crash stack delphi-xe3

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

动态链接不会改变行为。

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:0)

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

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

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