尝试捕获在共享库中不起作用?

Try-catch doesn't work in shared library?

本文关键字:不起作用 共享      更新时间:2023-10-16

(这是我的另一个问题但这是另一个问题,即使它是相关的)

我的项目遇到了一个大问题。我有一个库处理XML,可以抛出异常。并且,使用它来创建配置文件类显示了我的第一个错误:异常根本不在库中处理,并且对于每个异常。

在库中我写:

try {
    throw std::exception();
}
catch (...)
{
    printf("caughtn");
}

但是,不处理异常,立即调用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 : %sn", ex.what ());
    } catch (...) {
        printf ("In C_Configuration : caughtn");
    }

    return true;
}

} // namespace ns

构建命令:

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 

注意:我给出了这个例子,但它像预期的那样工作,异常是在库中捕获的,不像在我的主项目中。如果你想了解更多,你可以在这里查看我的项目代码。

问题是:

  • try-catch块在库内;
  • try-catch块在库之外;
在任何情况下,异常都会在库内部抛出。但是,外部抛出的异常会在可执行代码中捕获:
int
main (int argc, char** argv)
{
    try {
        throw 1;
    } catch (...) {
        cout << "Caught" << endl;
    }
    // Useless code
    return 0;
}

此代码仅在输出中写入Caught

所以,我的问题很简单:是c++异常没有在库中处理,还是我只是忘记了编译标志?我需要在可执行代码中说明,异常工作正常。

谢谢你的帮助。

EDIT:哦,天哪,我错了。问题解决了。在构建配置的最深处,ld取代了g++。现在这个例外正常工作了。谢谢你的帮助。

很简单。不要在c++中使用ld。我在我的项目中更改了所有ld命令为g++,但似乎我忘记了这个库。

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

根据gcc手册:

如果一个库或主可执行文件应该抛出或捕获异常,你必须使用g++或GCJ驱动程序链接它,根据程序中使用的语言,或者使用选项-shared-libgcc,这样它就被链接到共享的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