2010-07-14 99 views
0

我试图使用lcc编译器从C调用DLL函数(通过GetProcAddress等)。该函数被调用并且一切顺利,但它看起来像堆栈的顶部被损坏。我试图玩调用约定(__stdcall/__cdecl),但没有帮助。由于DLL调用造成的奇怪堆栈损坏

不幸的是,我不能访问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编译器,并且没有调试支持。可能我必须在独立配置中重现此问题,但实现起来并不容易。

回答

2

听起来就像你使用MSVC,Debug + Windows + Registers在调用前后查看ESP的值如果不匹配,先改变函数指针声明中的调用约定如果它仍然不匹配,那么它是__stdcall,并且你没有猜到你需要正确传递的参数。

或者该函数可能会破坏堆栈框架,这不是不可能的。

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

+0

我同意函数指针声明。 – 2010-07-14 19:29:16

+0

不,我使用lcc,我不知道如何附加一个调试器(编译器实际上由Matlab调用)。函数的定义如下所示:“typedef unsigned char(CALLBACK Type_foo)(unsigned char); Type_foo * foo;”,它们中有少数具有不同的参数,但它们都显示相同的行为。什么是ESP,如果它是错误的,那么我想我的黑客行不通... – 2010-07-14 19:37:59

+0

那么,写一个小测试程序,以便您可以真正调试。 – 2010-07-14 19:56:00

1

这听起来像你是在正确的轨道上看着调用约定。你需要做的主要事情是确保调用者和被调用者都使用相同的约定。通常对于一个DLL,你希望使用__stdcall,但是如果(如你所说)你无法控制DLL,那么你需要修改你的代码来匹配它所做的。不幸的是,几乎不可能猜到那是什么 - 我非常肯定lcc(像大多数C和C++编译器)可以生成代码来使用各种约定。

基于你的黑客通过在堆栈上放置一个额外的dword工作,这听起来像你目前有一个不匹配的情况,即调用者和被调用者都试图从堆栈中清除参数(例如,调用者使用__cdecl和使用__stdcall的被调用者

+0

我试过__cdecl和__stdcall,结果是一样的。我还能尝试什么? – 2010-07-14 18:53:08

1

你可以尝试使用调试器“跟随”调用dll_foo(),我的汇编程序,在检查什么例程没有堆栈明智。