【问题标题】:Throwing from a C++ function called from a C function via pointer dereference通过指针取消引用从 C 函数调用的 C++ 函数中抛出
【发布时间】:2014-10-19 14:21:29
【问题描述】:

考虑在 C 库中定义的以下函数:

void f(void (*callback)(int)) { callback(0); }

将从定义callback()的C++11程序调用,可能会抛出异常,如下:

void callback(int) { /* can I throw ? */}
try {
   f(callback);
} catch (...) {
   /* can the exception be caught ? */
}

我的问题是:

  1. 标准是否允许在从f() 调用时抛出回调?如果不是,我必须/应该使用 noexcept 说明符声明 callback()
  2. 如果是,标准是否允许捕获被抛出的异常对象?

【问题讨论】:

  • 不允许 C++ 异常跨越到 C 堆栈。这个结果是不确定的。
  • 要符合标准,您必须将callback 声明为extern "C"。大多数实现都会让你忽略它,但严格来说,没有它,代码甚至不应该编译。 nothrow 不是必须的,只是不要扔。

标签: c++ c++11


【解决方案1】:

以下源码可以编译。

异常.cpp:

extern "C"
void throwInCPP() {
    throw 5;
}

main.c

#include <stdio.h>
void throwInCPP();
void throwExp(void (*callback)()) {
    callback();
}

int main() {
    throwExp(throwInCPP);
    return 0;
}

当它运行时,将抛出异常并且程序展开堆栈尝试找到一个catch块但它找不到。然后中止发生:

#0  0x00007ffff7238d67 in raise () from /usr/lib/libc.so.6
#1  0x00007ffff723a118 in abort () from /usr/lib/libc.so.6
#2  0x00007ffff7b2e1f5 in __gnu_cxx::__verbose_terminate_handler() ()
       from /usr/lib/libstdc++.so.6
#3  0x00007ffff7b2c076 in ?? () from /usr/lib/libstdc++.so.6
#4  0x00007ffff7b2c0c1 in std::terminate() () from /usr/lib/libstdc++.so.6
#5  0x00007ffff7b2c2d8 in __cxa_throw () from /usr/lib/libstdc++.so.6
#6  0x00000000004007fa in throwInCPP ()
#7  0x00000000004007bd in throwExp (callback=0x4007d4 <throwInCPP>) at main.c:6
#8  0x00000000004007cd in main () at main.c:11

我认为你总是可以调用一个 cpp 函数,它在 c 中抛出一个期望,但你永远不能在 c 中放置一个 catch 块,因为它不能编译。

How is the C++ exception handling runtime implemented? 这解释了异常在 c++ 中是如何工作的。

我真的不认为在 c 中抛出异常会是一件好事,因为你不能以“正常”的方式对它做任何事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多