【问题标题】:Is there an equivilant of _set_purecall_handler() in Linux?Linux 中是否有 _set_pure 调用 handler() 的等价物?
【发布时间】:2014-08-26 16:11:31
【问题描述】:

我想用我自己的覆盖纯虚拟调用 (__cxa_pure_virtual()) 的标准处理程序。 Windows 的答案是“_set_purecall_handler()”。

Linux/GNU 中有类似的工具吗?

【问题讨论】:

    标签: c++ c linux gcc gnu


    【解决方案1】:

    你差一点就自己回答了这个问题。这是gcc/libstdc++-v3/libsupc++/pure.cc中__cxa_pure_virtual的来源:

    extern "C" void
    __cxxabiv1::__cxa_pure_virtual (void)
    {
      writestr ("pure virtual method called\n");
      std::terminate ();
    }
    

    因此,没有直接等同于 Microsoft 的 _set_purecall_handler 与 GCC。但是,由于此函数调用了std::terminate,因此您可以使用std::set_terminate 设置一个处理程序,该处理程序在打印消息后被调用。

    另一种可能的解决方案是提供您自己的__cxxabiv1::__cxa_pure_virtual 定义,它会覆盖库函数。像这样的:

    namespace __cxxabiv1 {
            extern "C" void
            __cxa_pure_virtual(void) {
                    char const msg[] = "my pure virutal\n";
                    write(2, msg, sizeof msg - 1);
                    std::terminate();
            }
    }
    

    【讨论】:

    • 谢谢!您的两个建议都是中肯的(我确实查看了 pure.cc 的源代码,但不知道 std::set_terminate())。事实上, std::terminate() 正是我想要绕过的。所以std::set_terminate() 是(足够接近的)答案!
    • 所以这是一个弱符号,否则违反ODR。
    • @user877329 否 __cxxabiv1::__cxa_pure_virtual 并不意味着被覆盖,所以它只是一个普通的符号。就 C++ 标准而言,在您自己的代码中定义具有此名称的内容违反了禁止使用带有双下划线的标识符的规则。所以我的第二个建议不是可移植的,但它并不意味着是。它是使用 _set_purecall_handler 的替代方案,它也不是可移植的。
    • @RossRidge:不可移植和未定义之间存在巨大差异。 _set_purecall_handler 不违反 ODR,因此即使它不可移植,但定义明确。我试图重新定义__cxa_pure_virtual,但我没有收到任何链接器错误,而且它是我自己的,所以它必须是一个弱符号,但nm将它列为T,奇怪。
    • @user877329 不,未定义只是意味着标准没有定义会发生什么。这并不意味着特定的行为不会发生,它只是意味着你不能依赖于可移植的行为。在这种情况下,我的第二个建议取决于标准未定义的以下行为。 1) 编译器编译器在调用纯虚函数时生成调用 __cxa_pure_virtual 的代码。 2) 链接器更喜欢目标文件中的符号定义而不是库中的定义。它不依赖于库中的符号是弱的。其实不然。
    【解决方案2】:

    如果不启用任何额外的警告,g++(4.5 测试)将告诉您您正在从构造函数/析构函数调用抽象函数,这应该消除设置自定义处理程序的任何需要。

    由于有效的 C++ 程序永远不会导致纯虚拟调用,我假设您在 Windows 上设置了此处理程序用于诊断/调试目的。在这种情况下,在编译时而不是运行时进行诊断似乎要容易得多。

    【讨论】:

    • 没有。我不是在谈论编译时错误处理。这个问题是关于“运行时”异常处理(即每当__cxa_pure_virtual() 被调用时)。
    • 不,我没有在 Windows 中设置这个处理程序。我只是搜索它,发现答案仅适用于 Windows。是的,一个 Linux g++ 编译的应用程序可以并且确实在运行时结束了这个调用。所讨论的特定应用程序没有任何编译时错误。这是一个复杂的多线程应用程序,其中派生类对象的实例恰好在运行时“消失”,导致这个“纯虚拟调用”的系统异常。
    • 仅供参考,这里是 gdb 输出:这是针对这种情况的 gdb 回溯:#5 0x4015b7f4 in __cxxabiv1::__cxa_pure_virtual () at XXXX/src/gcc/libstdc++-v3/libsupc++/pure.cc:55
    猜你喜欢
    • 2021-03-01
    • 2013-03-20
    • 1970-01-01
    • 1970-01-01
    • 2011-07-29
    • 2013-06-21
    • 2014-01-09
    • 2012-02-18
    相关资源
    最近更新 更多