web-dev-qa-db-ja.com

CライブラリにTHROWが表示されるのはなぜですか?

私がするとき:less /usr/include/stdio.h(これはCライブラリのみです-C++とは関係ありません)

かなりの数の関数宣言の後に__THROWが表示されます。また、いくつかの関数の上のコメントは、「この関数はキャンセルポイントの可能性があるため、__THROWでマークされていません」と述べています。これは何のためですか?

throwは例外処理用です...しかし、私が知る限り、Cはそれをサポートしていません。

説明してください。

39
mynk

このヘッダーは、そのベンダーの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ヘッダーを含めるには<stdlib.h> C++では、<cstdlib>。したがって、C++と関係があります。 :)

これが、実行するコードが表示される理由です。 2つの異なる言語のヘッダーを複製することは、メンテナンスと清潔さにとって悪夢です。

42
GManNickG

できるよ

_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 次のようになります。

この属性を使用した外部関数の呼び出しは、returnまたは例外処理によってのみ現在のコンパイル単位に戻る必要があります。特に、リーフ関数は、現在のコンパイルユニットから渡されたコールバック関数を呼び出したり、ユニットによってエクスポートされた関数を直接呼び出したり、ユニットにlongjmpしたりすることはできません。リーフ関数は、他のコンパイルユニットから関数を呼び出す可能性があるため、関数呼び出しがまったく含まれていないという意味で、必ずしもリーフであるとは限りません。この属性は、データフロー分析を改善するためのライブラリ関数を対象としています。コンパイラーは、現在のコンパイル単位をエスケープしていないデータは、leaf関数で使用または変更できないというヒントを受け取ります。たとえば、sin関数はleaf関数ですが、qsortはそうではありません。

リーフ関数は、静的変数を使用する現在のコンパイルユニットで定義されたシグナルハンドラーを間接的に実行する可能性があることに注意してください。同様に、レイジーシンボル解決が有効な場合、リーフ関数は、リゾルバー関数または実装関数が現在のコンパイルユニットで定義され、静的変数を使用する間接関数を呼び出す場合があります。このようなシグナルハンドラー、リゾルバー関数、または実装関数を作成するための標準準拠の方法はありません。できる最善の方法は、リーフ属性を削除するか、このような静的変数をすべて揮発性としてマークすることです。最後に、シンボル挿入をサポートするELFベースのシステムの場合、現在のコンパイルユニットで定義された関数が、定義された標準モードと定義された機能テストマクロに基づいて他のシンボルを予期せず挿入しないように注意する必要があります。そうしないと、不注意によるコールバックが追加されます。

この属性は、現在のコンパイル単位内で定義されている関数には影響しません。これは、たとえばリンク時の最適化を使用して、複数のコンパイル単位を1つに簡単にマージできるようにするためです。このため、この属性は、間接呼び出しに注釈を付けるタイプでは許可されていません。

nothrow

nothrow nothrow属性は、関数が例外をスローできないことをコンパイラーに通知するために使用されます。たとえば、標準Cライブラリのほとんどの関数は、関数ポインタ引数をとるqsortとbsearchの注目すべき例外を除いて、例外をスローしないことを保証できます。

Cでの__attribute__((nothrow))の意味は、 gcc-属性nothrowは何に使用されますか? で答えられます。基本的には、C++コードとの連携用であり、関数が例外をスローするC++コードをコールバックしない場合に使用できます。

8
PSkocik

「この関数はキャンセルポイントの可能性があるため、__ THROWのマークが付いていない」に関する他の質問に答えるには:これはマルチスレッドを扱います。スレッドを「キャンセル」することはできますが、キャンセルポイントに達するまで実際には「キャンセル」されません。さらに詳しい情報: http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_cancel.3.html

5
Ioan