1

Cで実装されたシリアルおよびソケットIO (Linux / Windows)を抽象化する関数があります。それらはすべて、extern "C"C ++からも呼び出される可能性があるため、としてマークされています。

__attribute__((__nothrow__))ここで(または MinGW マクロ)を使用しても安全です__MINGW_NOTHROWか / 例外がスローされないと仮定できますか?

呼び出される関数 - ソケット:
(リストされている WinSock のすべての追加ではありません)

  • socket
  • connect
  • send/recv
  • close( closesocketWindows の場合)
  • 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)。

4

2 に答える 2

5

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)キャンセル ポイントであるため、 のマークは ありません__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) 私の質問にリストされているものについてのみ話します。

于 2013-03-02T20:52:47.953 に答える
1

nothrowgcc 3.3 で導入されたgcc バージョンに注意してください。

mingw__THROWから移植できます:sys/cdefs.h

/* 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を参照してください。

edit: __GNUC_PREREQに置き換えることができるので__MINGW_GNUC_PREREQ(major, minor)、上記のように再定義する必要はありません。

于 2013-03-02T23:16:54.943 に答える