Android NDK C++ 异常抛出 SIGSEGV 和 __gnu_cxx::__verbose_terminate_handler

标签 android c++ android-ndk

我想在我的 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 到标志,但是当用户代码抛出异常时 vm 仍然中止,catch block 中的代码没有被执行。

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

标志:

Android.mk 中: LOCAL_CPP_FEATURES += 异常

Application.mk中: APP_CPPFLAGS += -fexceptions APP_CFLAGS += -fexceptions

我还尝试过强制重建 STLport 和 libcxx,并使用 gcc-4.6gcc-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;
};

我使用: 抛出 MyNativeException("消息")

更新 好的,这个异常定义确实有效:

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

前面哪里出了问题?

最佳答案

您的问题与将 C++ 与 Java 混淆有关。

抛出新的 std::exception();

上面那行代码在 Java 中可能一切都很好,但在 C++ 中就不同了。

  1. 您正在从自由存储区分配内存以创建一个对象。

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

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

如果您有一个捕获指针值的 catch block ,那么您会看到这一点。

例如:

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. 您的编译器有问题,或者您需要设置一个开关来启用异常处理。

关于Android NDK C++ 异常抛出 SIGSEGV 和 __gnu_cxx::__verbose_terminate_handler,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25130192/

相关文章:

C++ cUrl 将多部分/表单数据文件发送到 Web 服务器

c++ - 在 Visual Studio 中运行教程 - 什么样的 "New Project"?

android - 使用 std::map 时 _Rb_tree_rebalance_for_erase 中的空指针取消引用崩溃

android - 如何将位图设置为从相机捕获的 main.xml 中的 ImageView?

c++ - 确保某些私有(private)函数只能从锁定状态调用

android - 如何连接或使用 NDK 和 Nativescript vuejs

android - 使用通过 CMAKE 构建的 Android NDK 时如何获取构建类型?

java - 安卓有线网络如何切换?

java - 从 xml 运行另一个 Activity

Android Studio CMake 错误 : Build Command failed