Try-catch在共享库中不起作用?

时间:2016-08-10 16:33:09

标签: c++ c++11 exception exception-handling

(这就像my other question,但这个是另一回事,即使它是相关的)

我的项目中存在一个大问题。我有一个处理XML的库,可以抛出异常。并且,使用它来创建配置文件类会显示我的第一个错误:库中根本没有处理异常,并且每个例外都没有处理异常。

在我写的图书馆中:

try {
    throw std::exception();
}
catch (...)
{
    printf("caught\n");
}

但是,未处理异常并立即调用std::terminate

terminate called after throwing an instance of 'std::exception'
  what():  std::exception

编译标志是最简单的:文件库为-fPIC -std=c++11 -g -Wall,可执行文件为-std=c++11 -g -Wall(加上库和变体构建定义)。另外,我在Linux下使用G ++ 5.4.0(确切地说是Linux Mint)。

这是我的main

#include "ns/core/C_Configuration.hpp"

#include <iostream>

using namespace std;
using namespace ns;


int
main (int argc, char** argv)
{
    try {
        C_Configuration c ("test.xml");
        c.load ("test.xml");
    } catch (const std::exception& ex) {
        cout << ex.what () << endl;
    } catch (...) {
        cout << "Caught." << endl;
    }


    return 0;
}

C_Configuration.hpp

#include <string>
#include <exception>


namespace ns
{


    class C_Configuration
    {

    public:

        C_Configuration (std::string);


        bool load (std::string file);

    };


} // namespace ns

而且,这是C_Configuration.cpp

#include "ns/core/C_Configuration.hpp"

#include <cstdio>

using namespace std;


namespace ns
{



C_Configuration::C_Configuration (string)
{ }



bool
C_Configuration::load (string file)
{

    try {
        throw exception();
    } catch (const exception& ex) {
        printf ("In C_Configuration : %s\n", ex.what ());
    } catch (...) {
        printf ("In C_Configuration : caught\n");
    }


    return true;
}


} // namespace ns

Buid命令:

g++ -m64 -g -shared -fPIC -std=c++11 -o libns_framework.so C_Configuration.cpp
g++ -m64 -g -L. -o exe main.cpp -lns_framework 

注意:我举了这个例子,但它按预期工作,异常会在库中捕获,而不是像我的主项目中那样。如果您想进一步调查,可以查看我的项目代码here

问题出在:

  • try-catch块是里面库;
  • try-catch块库外;

在任何情况下,异常都会在内部库中抛出。但是,外部抛出的异常会被可执行代码捕获:

int
main (int argc, char** argv)
{
    try {
        throw 1;
    } catch (...) {
        cout << "Caught" << endl;
    }

    // Useless code

    return 0;
}

此代码只在输出中写入Caught

所以,我的问题很简单:C ++异常是否在库中处理,或者我忘记了编译标志?我需要在可执行代码中说,例外工作正常。

感谢您的帮助。

编辑:天啊,我的坏人。问题解决了。在我的构建配置的最深部分,ld代替了g++。现在异常工作正常。谢谢你的帮助。

2 个答案:

答案 0 :(得分:2)

根据gcc manual

  

如果库或主可执行文件应该抛出或捕获异常,则必须使用G ++或GCJ驱动程序链接它,以适合程序中使用的语言,或使用选项 -shared-libgcc < / strong>,这样它就与共享的libgcc链接。

共享库(在C ++和Java中)默认设置该标志,但不是主可执行文件。无论如何,你应该在两者上使用它。

测试用例:

lib.cpp

#include "lib.hpp"
#include <string>
#include <iostream>

using namespace std;

int function_throws_int() {
    try {
        throw 2;
    }
    catch (...) {
        cout << "int throws lib" << endl;
        throw;
    }

    return -1;
}

int function_throws_string() {
    try {
        throw std::string("throw");
    }
    catch (...) {
        cout << "throws string lib" << endl;
        throw;
    }
}

lib.hpp

int function_throws_int();
int function_throws_string();

编译命令行g++ -m64 -g -shared-libgcc -shared -fPIC -std=c++11 -o libtest.so lib.cpp

的main.cpp

#include "lib.hpp"
#include <string>
#include <iostream>

using namespace std;

int main(int argc, char ** argv) {
    try {
        function_throws_int();
    }
    catch (const string & e) {
        cout << "string caught main" << endl;
    }
    catch (int i) {
        cout << "int caught main" << endl;
    }

    return 0;
}

编译命令行g++ -m64 -g -shared-libgcc -o main -L. main.cpp -ltest

<强>执行LD_LIBRARY_PATH=. ./main

<强>输出

int throws lib
int caught main

答案 1 :(得分:1)

简单。切勿在{+ 1}}中使用C ++。我将项目中的所有ld命令更改为ld但似乎我忘了这个库。

简而言之,我使用g++来构建我的库,但ld用于主可执行文件。因此,异常在可执行文件中有效但在库中没有,因为g++不包括处理异常系统的C ++库。