为什么我在C库中看到THROW?

时间:2010-03-21 08:16:39

标签: c++ c exception header-files

当我这样做时: less /usr/include/stdio.h(这只是一个C库 - 与C ++无关)

在很多函数声明后我看到__THROW。 此外,一些函数上面的注释表示'此函数是一个可能的取消点,因此没有标记为__THROW' 这是为了什么?

throw用于异常处理...但据我所知,C不提供任何支持。

请解释。

3 个答案:

答案 0 :(得分:40)

此标头可能在该供应商的C和C ++编译器之间共享。你看看__THROW被定义为什么?

我怀疑类似于:

#ifdef __cplusplus
    #define __THROW throw()
#else
    #define __THROW
#endif

或实际规格:

#ifdef __cplusplus
    #define __THROW(x) throw(x)
#else
    #define __THROW(x)
#endif

正如您所看到的,在C版本中,它扩展为空。在C ++中,它可以满足您的期望。这允许供应商重用相同的文件。


只是为了挑剔,这并不完全正确:“(这只是一个C库 - 与C ++无关)”

C ++标准库包括使用C标准库的功能。实际标头为<cxxx>,其中xxx是C标头名称。也就是说,要在C ++中包含C标头<stdlib.h>,您需要<cstdlib>。所以它确实与C ++有关。 :)

这就是你看到你所做的代码的原因。复制两种不同语言的标题将是维护和清洁的噩梦。

答案 1 :(得分:5)

要回答您关于“此功能是可能的取消点,因此未标记为__THROW”的其他问题:这涉及多线程。你可以“取消”一个线程,但在到达取消点之前它实际上不会“取消”。更多信息:http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_cancel.3.html

答案 2 :(得分:4)

你可以做到

cpp -include stdlib.h -dM /dev/null  |grep '#define __THROW '

了解它实际扩展到的内容。

在我的系统上,我得到:

#define __THROW __attribute__ ((__nothrow__ __LEAF))

nothrow leaf 属性描述于 https://gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/Common-Function-Attributes.html#Common-Function-Attributes 如下:

<强>叶

  

leaf使用此属性调用外部函数必须返回   当前编译单元只能通过返回或异常处理。   特别是,不允许叶函数调用回调   函数直接从当前编译单元传递给它   调用本机输出的函数,或longjmp进入单元。叶   函数可能仍然从其他编译单元调用函数   因此,它们不一定是叶子,因为它们不含有   函数调用。该属性适用于库函数   改进数据流分析。编译器接受任何提示   不能使用当前编译单元的数据或不能使用   由叶函数修改。例如,sin函数是叶子   功能,但qsort不是。

     

请注意,叶函数可能间接运行定义的信号处理程序   在当前使用静态变量的编译单元中。同样的,   当惰性符号解析生效时,叶子函数可能会调用   其解析器功能或实现功能的间接功能   在当前编译单元中定义并使用静态变量。   没有符合标准的方法来编写这样的信号处理程序,   解析器功能或实现功能,以及您的最佳功能   可以做的是删除叶属性或标记所有这样的静态   变量volatile。最后,对于支持符号的基于ELF的系统   介入时,应注意定义的功能   当前编译单元不会意外插入其他符号   基于定义的标准模式和定义的特征测试宏;   否则会添加无意的回调。

     

该属性对当前定义的函数没有影响   编译单位。这是为了容易合并多个   例如,通过使用链接时间将编译单元合并为一个   优化。因此,类型不允许使用该属性   注释间接调用。

<强>抛出异常

  

nothrow nothrow属性用于通知编译器a   函数不能抛出异常。例如,大部分功能都在   标准C库可以保证不会抛出异常   带有函数指针的qsort和bsearch的值得注意的例外   参数。

gcc - what is attribute nothrow used for?回答了__attribute__((nothrow))在C中的含义。基本上,它与C ++代码的合作,如果函数不会回调抛出异常的C ++代码,你可以使用它。