我有用C语言实现抽象 serial - 和 socket IO (Linux / Windows)的函数。
所有这些都标记为extern "C"
,因为它们也可以从C ++调用。
在这里使用__attribute__((__nothrow__))
(或MinGW Macro __MINGW_NOTHROW
)是否安全/我可以假设没有抛出任何异常吗?
被叫函数 - 套接字:
(并非列出所有WinSock的附加内容)
socket
connect
send
/ recv
close
(Windows上为closesocket
)sendto
/ recvfrom
被叫函数 - 序列号:
由于串口IO代码在windows / linux之间存在很大差异,因此这里没有列出
open
tcgetattr
read
/ write
close
CreateFile
GetCommState
/ SetCommTimeouts
ReadFile
/ WriteFile
CloseHandle
由于 ANSI C 没有异常(如果我错了请纠正我),它们不会被抛出,但GCC扩展和OS API调用怎么样?
文档:http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html(请参阅nothrow
)。
答案 0 :(得分:4)
GNU C(Linux)使用__THROW
宏而不是__MINGW_NOTHROW
。
虽然MinGW仅属于__nothrow__
属性,但__THROW
也包含__leaf__
属性。
如果使用C ++,__THROW
具有另一个含义:throw()
- 表示不抛出任何异常(类似于__nothrow__
;但在C ++标准中定义。)
所以这取决于你是用
示例:强>
void f() __THROW;
被视为......
GNU C:
void f() __attribute__((__nothrow__, __leaf__))
GNU C ++:
void f() throw()
函数 1)是取消点,因此未标记
__THROW
:
open()
read()
write()
close()
connect()
send()
recv()
close()
sendto()
recvfrom()
函数 1) 标记与__THROW
:
tcgetattr()
socket()
至少,这些保存到__nothrow__
。
相比之下, MinGW与C ++没有区别 C;在这两种情况下都设置了属性。
使用上面的示例,{C 和 C ++上设置了__nothrow__
:
void f() __attribute((__nothrow__))
函数 1) 未标记与__MINGW_NOTHROW
:
socket()
connect()
send()
recv()
closesocket()
sendto()
recvfrom()
CreateFile()
GetCommState()
SetCommTimeouts()
ReadFile()
WriteFile()
CloseHandle()
简而言之:无!
兼容性
使用C
期望与C ++互操作的C语言代码应该是 使用-fexceptions编译。这将使调试成为一种C语言 函数被称为C ++的一部分 - 可能导致堆栈展开。
特别是,在没有异常处理数据的情况下展开到帧中 将导致运行时中止。如果开卷机用完放松信息 在找到处理程序之前,调用std :: terminate()。
请注意,大多数开发环境都应该注意 获得这些细节是对的。对于GNU系统,所有适当的部分 GNU C库已经使用-fexceptions编译。
(来源:http://gcc.gnu.org/onlinedocs/libstdc++/manual/using_exceptions.html)
使用-fexceptions
进行编译,不需要等效属性。如果您只能标记特定功能,则必须使用__nothrow__
。
但是使用__nothrow__
属性看起来只保存在GNU C ++和Linux上的GNU C的一些功能上,在Windows上并不是那么清楚。
为了避免这个问题的某些部分,我编写了一个类似于__THROW
的宏,但也可用于MinGW:
#if defined __GNUC__
#ifndef __THROW
#ifdef __cplusplus
#define __THROW throw()
#else
#define __THROW __attribute__((__nothrow__))
#endif
#endif
#else
#define __THROW
#endif
注意: __leaf__
未包含在内。
1) 只谈论我提出的问题。
答案 1 :(得分:1)
照顾gcc版本,gcc 3.3引入了nothrow
!
您可以__THROW
从sys/cdefs.h
移植到mingw:
/* skip this entire part on linux (= glibc available)*/
#if defined __GNUC__ && !defined __linux__
/********* port __GNUC_PREREQ macro to mingw *********/
# if !defined __GNUC_PREREQ
# if !defined __MINGW_H
# include <_mingw.h>
# define __GNUC_PREREQ(major, minor) __MINGW_GNUC_PREREQ(major, minor)
# else
# if defined (__GNUC_MINOR__)
# define __GNUC_PREREQ(major, minor) __GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
# else
# define __GNUC_PREREQ(major, minor) 0
# endif
# endif
#endif /* __GNUC_PREREQ */
/********* from gnu c blirary *********/
/* All functions, except those with callbacks or those that
synchronize memory, are leaf functions. */
# if __GNUC_PREREQ (4, 6) && !defined _LIBC
# define __LEAF , __leaf__
# define __LEAF_ATTR __attribute__ ((__leaf__))
# else
# define __LEAF
# define __LEAF_ATTR
# endif
/* GCC can always grok prototypes. For C++ programs we add throw()
to help it optimize the function calls. But this works only with
gcc 2.8.x and egcs. For gcc 3.2 and up we even mark C functions
as non-throwing using a function attribute since programs can use
the -fexceptions options for C code as well. */
# if !defined __cplusplus && __GNUC_PREREQ (3, 3)
# define __THROW __attribute__ ((__nothrow__ __LEAF))
# define __THROWNL __attribute__ ((__nothrow__))
# define __NTH(fct) __attribute__ ((__nothrow__ __LEAF)) fct
# else
# if defined __cplusplus && __GNUC_PREREQ (2,8)
# define __THROW throw ()
# define __THROWNL throw ()
# define __NTH(fct) __LEAF_ATTR fct throw ()
# else
# define __THROW
# define __THROWNL
# define __NTH(fct) fct
# endif
# endif
#else /* Not GCC. */
# define __inline /* No inline functions. */
# define __THROW
# define __THROWNL
# define __NTH(fct) fct
#endif /* GCC. */
请参阅glibc - sys/cdefs.h了解完整代码。
编辑: __GNUC_PREREQ
可以替换为__MINGW_GNUC_PREREQ(major, minor)
,然后您不必像上面那样重新加工。