Serial- / Socket IO和GCC nothrow属性

时间:2012-12-03 19:51:08

标签: c gcc io mingw

我有用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之间存在很大差异,因此这里没有列出

  • Linux(GNU)
    • open
    • tcgetattr
    • read / write
    • close
  • Windows(MinGW)
    • CreateFile
    • GetCommState / SetCommTimeouts
    • ReadFile / WriteFile
    • CloseHandle

由于 ANSI C 没有异常(如果我错了请纠正我),它们不会被抛出,但GCC扩展和OS API调用怎么样?

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

2 个答案:

答案 0 :(得分:4)

C

GNU C(Linux)使用__THROW宏而不是__MINGW_NOTHROW。 虽然MinGW仅属于__nothrow__属性,但__THROW也包含__leaf__属性。

C ++

如果使用C ++,__THROW具有另一个含义:throw() - 表示不抛出任何异常(类似于__nothrow__;但在C ++标准中定义。)

所以这取决于你是用 C ++ 编译,而不是用你所谓的函数来命令(仅限GNU C / 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

您可以__THROWsys/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),然后您不必像上面那样重新加工。