Android NDK c++异常抛出SIGSEGV和__gnu_cxx::__verbose_terminate_ha

Android NDK C++ exception throws SIGSEGV and __gnu_cxx::__verbose_terminate_handler

本文关键字:gnu cxx verbose ha terminate c++ NDK 异常 SIGSEGV Android      更新时间:2023-10-16

我想在我的JNI代码中抛出std::exception的子类,代码使用swig包装,但它并不真正相关,因为生成的代码相当简单:

void function_that_throws_exception() {
    ...
    throw MyNativeException("Error");
}
try {
    function_that_throws_exception();
} catch(MyNativeException &_e) {
    jclass excep = jenv->FindClass("x/y/zMyNativeException");
    if (excep)
        jenv->ThrowNew(excep, (&_e)->what());
    return 0;
}

我已经添加了-fexception的标志,但虚拟机仍然中止时,用户代码抛出异常,在catch块代码不执行。

我已经测试了不同的cpp实现,gnustl_static引发__gnu_cxx::__verbose_terminate_handler,看起来异常没有处理,stlport_static调用abort()

标记:

in Android.mk:LOCAL_CPP_FEATURES += exceptions

in Application.mk:APP_CPPFLAGS += -fexceptionsAPP_CFLAGS += -fexceptions

我也尝试过强制重建stlport和libcxx,并使用gcc-4.6, gcc-4.8clang

即使这个简单的代码也会终止

try
{
    throw new std::exception();
} catch (std::exception &e) {
}

如果我用std::set_terminate设置了一个终止函数,我的函数被调用了,它显然没有被捕获

不带"new"的简单代码可以工作,所以我怀疑我的异常有问题:

class MyNativeException : public std::exception
{
public:
    explicit MyNativeException(const char *msg) : message(msg) {}
    virtual ~MyNativeException() throw() {}
    virtual const char *what() const throw() { return message.c_str(); }
protected:
    const std::string message;
};

我使用:throw MyNativeException("message")

这个异常定义确实有效:

class MyNativeException
{
public:
    MyNativeException(const char *msg) : message(msg) {}
    ~MyNativeException() {}
    const char *what() { return message.c_str(); }
private:
    const std::string message;
};

前面有什么问题?

你的问题与混淆c++和Java有关。

throw new std::exception();

上面这行在Java中可能很好,但在c++中则是另一回事。

  1. 你正在从free-store分配内存来创建一个对象。

  2. 但最重要的是,c++中的new返回一个指针,该指针指向动态分配的内存,必须使用delete释放。与Java中的new不一样

所以c++中的那行代码抛出的是指针值,而不是对象。不幸的是,您没有检测到这个问题,因为在c++中您几乎可以抛出任何东西——std::exception对象、int、指针值等。

如果你有一个捕获指针值的catch块,那么你会看到这个

例如:

try
{
   throw new std::exception();
} 
catch (std::exception *e) 
{
   delete e;
}

但是很容易纠正你的尝试:

try
{
   throw std::exception();
} 
catch (std::exception &e) 
{
}
为了确认,下面是一个小而完整的程序,它抛出异常并捕获以下内容:
#include <exception>
#include <string>
#include <iostream>
class MyNativeException : public std::exception
{
    public:
         explicit MyNativeException(const char *msg) : message(msg) {}
         virtual ~MyNativeException() throw() {}
         virtual const char *what() const throw() { return message.c_str(); }
    protected:
         const std::string message;
};
int main()
{
    try
    {
        throw MyNativeException("abc123");
    }
    catch (std::exception& e)
    {
        std::cout << e.what();
    }
}

输出:abc123

我上了你的课,实际上抛出了你声称不会被捕获的异常。上面代码中的异常确实被捕获了,因此问题的唯一结论是您是

  1. 没有抛出你声称正在抛出的异常,或者

  2. 您正在错误地抛出它(正如new问题所指出的那样),或

  3. 你的编译器坏了,或者你需要设置一个开关来启用异常处理