是否存在标准调用约定



我最近在custm CALLBACK的函数指针方面遇到了问题,这归结为使用调用约定来暂时解决问题,当时funy CALLBACK确实工作得很好,但调用函数的签名仍然是错误的!!我花了很多时间找到BUG。意识到caling惯例有时会让你做一些不好的事情。。。

好吧,现在已经过去了。。。现在,我想了解更多关于调用约定的信息:Visual Studio有自己的__cdecl__thiscall等(IIRC)。

标准C++是否规范了一些调用约定?如果是,我该如何使用它们?


编辑:我未能找到错误的一些代码

    class Object;
    class EventArgs;
    typedef void(__cdecl Object::*MethodHandler)(Object* sender, EventArgs args);
///..... this is how I call it..(snapshot)
(iter->second.sender->*iter->second.memberFunct)(sender, args);
///...
    void __cdecl Triger(EventArgs args) //missing "Object* sender" here!!! but it works!
    {
        if(args == "test")
        cout << "test args received" << endl;
    }

(顺便说一句,类型名称是我的自定义类。)效果很好!函数被调用,但没有__cdecl,我收到ESP寄存器错误。

否;调用约定是特定于平台的。前导双下划线表明这是一个保留实现的概念。语言本身对如何在这个细节级别上实现它没有任何要求。

在没有__cdecl的情况下崩溃的原因是因为Windows编译器默认使用__stdcall。后者强制被调用方函数清理堆栈。因此,您的调用方将两个参数推到堆栈上以调用"Trigger",但Trigger在函数退出时仅从堆栈中弹出一个参数。因此,你崩溃了__cdecl调用约定可以绕过这一点。

正如我在上面的评论中所说,使用__cdecl来修复崩溃隐藏了真正的错误。触发器的参数列表与"MethodHandler"所需的参数列表不匹配。这很可能是你撞车的原因。

这可能是一个更好的解决方案:

typedef void(Object::*MethodHandler)(Object* sender, EventArgs args);
void Triger(Object* sender, EventArgs args)
{
    if(args == "test")
    cout << "test args received" << endl;
}

您没有分享显示"触发器"如何为后续回调注册的代码。但我强烈怀疑你投下了这样的东西:

MethodHandler handler = (MethodHandler)Trigger;

因为如果你不这样做,你的代码就不会编译。修复你的代码,这样编译就不需要强制转换了,你真正的bug和崩溃都会消失。

最新更新