0

我正在尝试使用 lcc 编译器从 C 调用 DLL 函数(通过 GetProcAddress 等)。该函数被调用并且一切顺利,但看起来堆栈的顶部已损坏。我尝试使用调用约定(__stdcall / __cdecl),但这没有帮助。

不幸的是,我无法访问 dll 代码,必须使用 lcc 编译器。

我发现这个简单的技巧可以避免堆栈损坏:

void foo(params)
{
  int dummy;
  dll_foo(params);
}

这里的 dll_foo 是 GetProcAddress 返回的指针,并且堆栈受到虚拟变量的保护。因此,损坏的不是堆栈指针,而是堆栈顶部的数据。它是这样工作的,但我想知道腐败的原因。

有任何想法吗?

UPD:正如评论中所问的,这里是实际的函数类型:

typedef unsigned char (CALLBACK Tfr)(unsigned char);
typedef void (CALLBACK Tfw)(unsigned char,unsigned char);
typedef int (CALLBACK Tfs)(int);
typedef void (CALLBACK Tfwf)(int*,int);

他们都表现出类似的行为。

不幸的是,附加调试器并不是那么简单,因为代码是由 Matlab 编译和启动的,使用 LCC 编译器,并且没有调试支持。可能我将不得不在独立配置中重现此问题,但要做到这一点并不容易。

4

3 回答 3

2

听起来您使用 MSVC、Debug + Windows + Registers。查看调用前后 ESP 的值。如果不匹配,则首先更改函数指针声明中的调用约定(您这样做对吗?)如果仍然不匹配,则它是 __stdcall 并且您还没有猜到需要正确传递的参数。

或者该函数可能只是破坏堆栈帧,这并非不可能。

发布显示真实参数的函数指针声明可能有助于更好地诊断这一点。

于 2010-07-14T19:24:42.560 回答
1

在我看来,您在查看调用约定时走在了正确的轨道上。您需要做的主要事情是确保调用者和被调用者都使用相同的约定。通常对于 DLL,您希望__stdcall两者都使用,但如果(如您所说)您无法控制 DLL,那么您需要修改代码以匹配它正在执行的操作。不幸的是,几乎不可能猜出那是什么——我很确定 lcc(像大多数 C 和 C++ 编译器一样)可以生成使用各种约定的代码。

根据您通过在堆栈上放置一个额外的 dword 进行的破解工作,听起来您当前存在不匹配,其中调用者和被调用者都试图从堆栈中清除参数(例如,调用者使用__cdecl和被调用者使用__stdcall.

于 2010-07-14T18:44:32.523 回答
1

您可以尝试使用调试器“跟踪”对 dll_foo() i 汇编程序的调用,以检查例程在堆栈方面的确切作用。

于 2010-07-14T19:28:33.660 回答