我正在尝试使用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编译器编译和启动的,并且没有调试支持。可能我必须在独立配置中重现这个问题,但要做到这一点并不容易。
答案 0 :(得分:2)
听起来像是使用MSVC,Debug + Windows + Registers。在调用之前和之后查看ESP的值。如果它不匹配,那么首先在函数指针声明中更改调用约定(你这样做了吗?)如果它仍然不匹配那么它是__stdcall并且你没有猜到你需要正确传递的参数。
或者该功能可能只是破坏堆栈帧,这不是不可能的。
发布显示真实参数的函数指针声明可能有助于更好地诊断它。
答案 1 :(得分:1)
听起来我觉得你在正确的轨道上看着召唤大会。您需要做的主要是确保调用者和被调用者都使用相同的约定。通常对于DLL,您希望使用__stdcall
作为两者,但如果(如您所说)您无法控制DLL,则需要修改代码以匹配其正在执行的操作。不幸的是,几乎不可能猜到它是什么 - 我很确定lcc(像大多数C和C ++编译器一样)可以生成使用各种约定的代码。
基于你的hack工作,在堆栈上添加一个额外的dword,听起来你当前有一个不匹配的地方,调用者和被调用者都试图清除堆栈中的参数(例如,调用者使用{{1} }和被叫方使用__cdecl
。
答案 2 :(得分:1)
您可以尝试使用调试器“跟随”对dll_foo()i汇编程序的调用,检查该例程的堆栈方式。