在Mac OS X上的-fno-rtti共享库中多态捕获异常 [英] Polymorphically catching an exception in a -fno-rtti shared library on Mac OS X

查看:171
本文介绍了在Mac OS X上的-fno-rtti共享库中多态捕获异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用 f-no-rtti 构建一个共享库。在内部,这个库会抛出 std:invalid_argument 并捕获 std :: exception ,但是 catch



下面的代码重现了这个问题(g ++ 4.2,Mac OS X 10.6):

  // library.cpp:导出f(),用-fno-rtti编译
#include< stdexcept>
#include< iostream>
externC{
void f(){
try {
throw std :: invalid_argument(std :: exception handler);
} catch(std :: exception& e){
std :: cout<< e.what()<< \\\
;
} catch(...){
std :: cout<< ...处理程序\\;



code
$ b $ hr

  // main.cpp:主要的可执行文件,动态加载库
#include< dlfcn.h>
typedef void(* fPtr)();

int main(){
void * handle = dlopen(./libexception_problem.dylib,RTLD_LAZY);
fPtr p_f = reinterpret_cast< fPtr>(dlsym(handle,f));
p_f();






输出:

  MacBook-Pro:teste pfranco $#可以正常运行rtti 
MacBook-Pro:teste pfranco $ g ++ -c library.cpp &安培;&安培; g ++ -shared -o libexception_problem.dylib library.o&& g ++ main.cpp -o main&& ./main
std ::异常处理程序
MacBook-Pro:teste pfranco $#中断-fno-rtti
MacBook-Pro:teste pfranco $ g ++ -c -fno-rtti库。 cpp&& g ++ -shared -o libexception_problem.dylib library.o&& g ++ -fno-rtti main.cpp -o main&& ./main
...处理程序
MacBook-Pro:teste pfranco $#-no_dead_strip_inits_and_terms不会更改任何内容
MacBook-Pro:teste pfranco $ g ++ -c -no_dead_strip_inits_and_terms -fno-rtti library.cpp&& g ++ -no_dead_strip_inits_and_terms -shared -o libexception_problem.dylib library.o&& g ++ -fno-rtti -no_dead_strip_inits_and_terms main.cpp -o main&& ./main
...处理程序
MacBook-Pro:teste pfranco $#与共享库链接,但这并不总是一个选项
MacBook-Pro:teste pfranco $ g ++ -c -fno-rtti library.cpp&& g ++ -shared -o libexception_problem.dylib library.o&& g ++ -fno-rtti main.cpp -o main -L。 -lexception_problem&& ./main
std ::异常处理程序






只有当抛出的代码位于共享库中,并且只有捕获类型是实际异常的基类时才会发生这种情况 - catch(std :: invalid_argument&)可以正常工作, std :: logic_error& 不会。



有趣的是,即使在运行完全相同的命令时, Linux上也不会发生这种情况。



问题:


  1. 为什么会发生这种情况?这是一个错误,未定义的行为或设计?


  2. $ b如何使它工作,缺乏与库的链接?
    $ b

    非常感谢。

    解决方案

    结果发现这是Apple gcc的一个bug。不过,他们最近回复了我的错误报告,称它不会被修复。


    I'm building a shared library with f-no-rtti. Internally, this library throws std:invalid_argument and catches std::exception, but the catch clause is never entered.

    The following code reproduces the problem (g++ 4.2, Mac OS X 10.6):

    // library.cpp: exports f(), compiled with -fno-rtti
    #include <stdexcept>
    #include <iostream>
    extern "C" {
        void f() {
            try {
                throw std::invalid_argument("std::exception handler");
            } catch( std::exception& e) {
                std::cout << e.what() << "\n";
            } catch(...) {
                std::cout << "... handler\n";
            }
        }
    }
    


    // main.cpp: the main executable, dynamically loads the library
    #include <dlfcn.h>
    typedef void(*fPtr)();
    
    int main() {
        void* handle = dlopen( "./libexception_problem.dylib", RTLD_LAZY );
        fPtr p_f = reinterpret_cast<fPtr>( dlsym( handle, "f" ) );
        p_f();
    }
    


    Output:

    MacBook-Pro:teste pfranco$ # works fine with rtti
    MacBook-Pro:teste pfranco$ g++ -c library.cpp && g++ -shared -o libexception_problem.dylib library.o && g++ main.cpp -o main && ./main
    std::exception handler
    MacBook-Pro:teste pfranco$ # breaks with -fno-rtti
    MacBook-Pro:teste pfranco$ g++ -c -fno-rtti library.cpp && g++ -shared -o libexception_problem.dylib library.o && g++ -fno-rtti main.cpp -o main && ./main
    ... handler
    MacBook-Pro:teste pfranco$ #-no_dead_strip_inits_and_terms doesn't change anything
    MacBook-Pro:teste pfranco$ g++ -c -no_dead_strip_inits_and_terms -fno-rtti library.cpp && g++ -no_dead_strip_inits_and_terms -shared -o libexception_problem.dylib library.o && g++ -fno-rtti -no_dead_strip_inits_and_terms main.cpp -o main && ./main
    ... handler
    MacBook-Pro:teste pfranco$ # linking against the shared library works, but this isn't always an option
    MacBook-Pro:teste pfranco$ g++ -c -fno-rtti library.cpp && g++ -shared -o libexception_problem.dylib library.o && g++ -fno-rtti main.cpp -o main -L. -lexception_problem && ./main
    std::exception handler
    


    This only happens if the code that throws is in a shared library, and only if the caught type is a base class of the actual exception - catch(std::invalid_argument&) works fine, std::logic_error& doesn't.

    Interestingly, this doesn't happen on Linux, even when running the exact same commands.

    Questions:

    1. Why does this happen? Is this a bug, undefined behavior or by design?
    2. How could I make it work, short of linking against the library?

    Thanks a lot.

    解决方案

    Turns out this a bug on Apple's gcc. They've recently replied to my bug report saying it won't be fixed, though.

    这篇关于在Mac OS X上的-fno-rtti共享库中多态捕获异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆