c - Serial-/Socket IO 和 GCC nothrow 属性

标签 c gcc io mingw

我有抽象serial-socket IO (Linux/Windows) 用C 实现的函数。 它们都被标记为 extern "C",因为它们也可能被 C++ 调用。

在这里使用 __attribute__((__nothrow__))(或 MinGW 宏 __MINGW_NOTHROW)是否安全/我可以假设没有抛出异常吗?

调用函数 - 套接字:
(未列出所有针对 WinSock 的添加)

  • 套接字
  • 连接
  • 发送/接收
  • close(closesocket 在 Windows 上)
  • 发送到/recvfrom

调用函数 - 序列号:
由于串行 IO 代码在 windows/linux 之间差异很大,因此此处并未列出所有代码

  • Linux (GNU)
    • 打开
    • tcgetattr
    • 读取/写入
    • 关闭
  • Windows (MinGW)
    • 创建文件
    • GetCommState/SetCommTimeouts
    • ReadFile/WriteFile
    • 关闭句柄

因为 ANSI C 没有异常(如果我错了请纠正我)它们不会被抛出,但是 GCC 扩展和 OS API 调用呢?

文档:http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html (参见 nothrow)。

最佳答案

C

GNU C (Linux) 使用 __THROW 宏代替 __MINGW_NOTHROW。 MinGW 只有 __nothrow__ 属性,而 __THROW 也包含 __leaf__ 属性。

C++

如果你使用C++,__THROW还有另外一个意思:throw()——表示没有异常被抛出(类似于__nothrow__;但是在 C++ 标准中定义)。

所以这取决于您是用 C 还是 C++ 编译,而不是您调用函数的来源(仅限 GNU C/C++!)。

示例:

void f() __THROW;

被视为...

GNU C:

void f() __attribute__((__nothrow__, __leaf__))

GNU C++:

void f() throw()

函数1)取消点,因此未标记 __抛出:

  • open()
  • 读取()
  • write()
  • 关闭()
  • connect()
  • 发送()
  • recv()
  • 关闭()
  • sendto()
  • recvfrom()

函数1) __THROW标记:

  • tcgetattr()
  • 套接字()

至少,这些都保存到__nothrow__

相比之下,MinGW 没有区别 C 和 C++;在这两种情况下都设置了属性。

使用上面的示例,__nothrow__ 在 C C++ 上设置:

void f() __attribute((__nothrow__))

函数1)未标记__MINGW_NOTHROW:

  • 套接字()
  • connect()
  • 发送()
  • recv()
  • closesocket()
  • sendto()
  • recvfrom()
  • 创建文件()
  • GetCommState()
  • SetCommTimeouts()
  • ReadFile()
  • WriteFile()
  • CloseHandle()

简而言之:没有!

Compatibility

With C

C language code that is expecting to interoperate with C++ should be compiled with -fexceptions. This will make debugging a C language function called as part of C++-induced stack unwinding possible.

In particular, unwinding into a frame with no exception handling data will cause a runtime abort. If the unwinder runs out of unwind info before it finds a handler, std::terminate() is called.

Please note that most development environments should take care of getting these details right. For GNU systems, all appropriate parts of the GNU C library are already compiled with -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) 只谈论我的问题中列出的那些。

关于c - Serial-/Socket IO 和 GCC nothrow 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13690584/

相关文章:

c - OpenSSL 函数 EVP_EncryptFinal_ex 中的内存泄漏

gcc - 警告 : end of file not at end of a line; newline inserted Assembley

c - 具有相同功能的 C 中的 Makefile 错误

c++ - C/C++ 中的头文件,标准?

haskell - monads current "state of the art"是用纯语言做 IO 吗?

写入文件时转储​​ C 程序核心

php - 如何使用 PHP 将浏览器输出写入日志文件?

c++ - 是否可以仅从普通 C 或普通 C++ 控制屏幕上的像素而无需任何 opengl/directx 麻烦?

c - 在循环中提示输入 4 个选项,选项 1 获取数组的输入

c - 使用 MPI 同步主/从模型