Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Can C++;标记为Extern的函数;";扔? 我有C++函数,我想用外“C”声明,即使它们只在C++代码中调用。是的,我知道这很奇怪,但是我想做一些一致性的事情,因为我们混合了C和C++声明。我只想确保声明C++函数为外“C”不会影响投掷行为。_C++_Extern C - Fatal编程技术网

Can C++;标记为Extern的函数;";扔? 我有C++函数,我想用外“C”声明,即使它们只在C++代码中调用。是的,我知道这很奇怪,但是我想做一些一致性的事情,因为我们混合了C和C++声明。我只想确保声明C++函数为外“C”不会影响投掷行为。

Can C++;标记为Extern的函数;";扔? 我有C++函数,我想用外“C”声明,即使它们只在C++代码中调用。是的,我知道这很奇怪,但是我想做一些一致性的事情,因为我们混合了C和C++声明。我只想确保声明C++函数为外“C”不会影响投掷行为。,c++,extern-c,C++,Extern C,它看起来像这样: extern "C" void foo() {throw exception;} int bar() { try { foo(); } catch (exception e) { return 1; } } 以下是你问题的答案: 基本上你是抓不到的。(但是为什么你不编译它,试试?):< /p> < p>“C++函数可以标记为外部”C“抛出”? 是,即语言和编译器都不会阻止您这样做 NO> ,在这个意义上,如果抛出,它将是一个未定义

它看起来像这样:

extern "C" void foo() {throw exception;}

int bar()
{
    try
    {
        foo();
    } catch (exception e) { return 1; }
}

以下是你问题的答案:

基本上你是抓不到的。(但是为什么你不编译它,试试?):< /p> < p>“C++函数可以标记为外部”C“抛出”? ,即语言和编译器都不会阻止您这样做

<强> NO> <强>,在这个意义上,如果抛出,它将是一个未定义的行为,因为C++异常跨越语言边界。 在实践中:不要这样做。捕获异常并将其转换为错误代码,或其他语言可以理解的方法


因此,底线是:从标记为
extern“C”的函数中抛出异常
它将编译,但从标记为具有C链接的函数中抛出异常是未定义的行为。C没有异常,因此一般来说,您应该只返回一个错误代码和/或提供一个函数来返回关于上一个错误的信息

#include <exception>
extern "C" void foo() {throw std::exception();}
#包括
外部“C”void foo(){throw std::exception();}
很好地编译

然而,在这个问题上,我们的目标相对明确:

  • /EHa
    /EHs
    。。。告诉编译器假定声明为extern“C”的函数可能引发异常
  • /EHsc
    。。。告诉编译器假定声明为ExtNeN“C”的函数从不抛出C++异常

。如果从C++代码中抛出异常到实际的C代码中(不知道该如何处理异常),那么这些回答断言您正在调用未定义的行为。我认为是正确的,但你是问C++或C调用<代码>外部“C”<代码>函数吗?如果你从C++调用它们(而不是C),那么有一个不可避免的问题“为什么函数 Extn”C“< /代码>如果它们从不从另一种语言调用”,但是我认为只调用C++函数用<代码>外“C”来自C++的意思是没有语言边界交叉,因此没有未定义的行为。感谢所有为解答这个问题做出贡献的人。如果我理解正确,我的问题的最终答案是:extern“C”不会改变异常处理的方式。但是,抛出未捕获且跨越语言边界的异常具有未定义的行为。q:“extern“C”不会改变异常处理的方式”--我不会以这种方式阅读答案。具体来说,
/EHsc
则相反。“编译并尝试”对于行为未定义的语言来说从来都不是一个好主意。但它可能会导致您对代码的行为做出错误的假设,而实际上您根本不应该假设任何东西,因为它是未定义的,编译器可以用它做任何事情。@PiotrJaszkowski:它可能不会摧毁宇宙,但龙会把你的鼻子喷出来。尝试
未定义的行为
是毫无意义的,因为测试没有意义,你什么也学不到。当
未定义的行为
发生时,你不能说
。当你调用
未定义的行为时
你的代码基本上是坏的。@LokiAstari,有人问他们能抛出什么,答案是肯定的。如果从C++链接的函数直接调用外部“C”函数,则没有未定义的行为。从C调用相同的函数,未定义的行为。仅仅因为联系,不一定存在语言交叉,但这肯定是一种气味。@LokiAstari,我必须反对你的说法,“当它的
未定义的行为时,你不能说
”,“未定义的行为”对它是否能够或应该发生无关紧要。它只指定结果未定义。它并没有规定它永远不会发生。跨越边界的例外总是发生。C++->C;C++->Java;C++->Python。不同之处在于,大多数语言翻译库提供了一种捕获、翻译和重排异常到目标语言的工具。第一个假设是错误的:<代码>如果一个外部“C”函数直接从C++链接< /代码>的函数调用。如果它抛出其未定义的行为。C函数的ABI不包含允许堆栈展开所需的信息。我必须同意@LokiAstari。在我的代码中,我有一个C++调用一个代码>外部c>代码>函数,它抛出一个异常,并且它没有被捕获(即使使用<代码> catch(…)< />代码>。编译器是英特尔编译器(icpc)。所有代码都是用C++编写的,没有C。链接的差异似乎足以打破堆栈展开。+ 1,但是你错过了GCC回答中的一个链接注释:<代码> -FExcExcs< /Cord>。在gcc文档中:“…在编译需要与用C++编写的异常处理程序正确互操作的C代码时,可能需要启用此选项”。