9

setjmp/sigsetjmpへのポインターを使用する必要があるマルチプラットフォームコードを書いています。通常、それは行うのと同じくらい簡単です

#include <setjmp.h>
void * sigsetjmp_p = sigsetjmp;

ただし、ISOとPOSIXは、setjmp / sigsetjmpをマクロとして定義できると述べており、実際、私のLinuxボックスの場合はそうです。これがからの抜粋です/usr/include/setjmp.h

# define sigsetjmp(env, savemask)       __sigsetjmp (env, savemask)

問題は、引数をに渡してsigsetjmpいないため、マクロが展開されず、プレーンsigsetjmpシンボルがlibcで定義されていないことです。マクロ「黒魔術」を使って「__sigsetjmp」の名前を抽出できることを望んでいましたが、これまでのところ惨めに失敗しました。

別のオプションは __sigsetjmp直接使用することですが、これはサポートされているすべてのプラットフォームの拡張をチェックすることを意味します。これは私がやりたくないことです(したがって、この質問の理由)。

PS:私はマクロが嫌いです。

ノート:

これが必要な理由は少しわかりにくいですが、簡単にするために、ポインター比較を実行したいとします。

#include <setjmp.h>
int equals_sigsetjmp(void *p)
{
 void * sigsetjmp_p =  sigsetjmp;
 return p == sigsetjmp_p;
}

編集:

はいはい。sigsetjmp特定のプラットフォームでは関数ではない可能性があるため、ポインタを取得することを期待すべきではないことはわかっていますが、これでは問題は解決しません

実際には、私が知っているすべてのプラットフォームは、それを関数として実装します。

sigsetjump数年後には、特定のプラットフォームで機能しない場合が発生することに対処できます。しかし、私が対処したくないのは、サポートされているすべてのプラットフォームを調べsetjmp.hて、マクロ定義をチェックすることです。これは、現在の私の唯一のオプションです。

標準への参照に感謝しますが、純粋なものではなく、実用的な答えを得たいと思います。

4

3 に答える 3

2

標準で明示的に禁止されているため、これを移植可能にすることはできません (§7.13):

setjmpがマクロなのか、外部リンケージで宣言された識別子なのかは不明です。実際の関数(...)にアクセスするためにマクロ定義が抑制されている場合、動作は未定義です。

どのPOSIXにそれを追加するか

関数は関数と同等sigsetjmp()なければならないsetjmp()

ここでは関係のないいくつかの例外があります。

ご指摘については

私が知っているすべてのプラットフォームは、関数として実装しています

GCC ではsetjmp、組み込みであり、私は Clang を信じていsigsetjmpます。(ただし、C ライブラリには関数バージョンもある場合があります。)

于 2013-03-06T15:07:17.680 に答える
0

どうですか:

void my_sigsetjmp(sigjmp_buf env, int savesigs)
{
    sigsetjmp(env, savesigs);
}

次に &my_sigsetjmp のアドレスを使用します

于 2014-06-26T16:59:15.820 に答える
-1

あなたが望むと言うもののために、私は次のようなことをします:

#include <setjmp.h>
#ifdef sigsetjmp
#define AVOID_FUNCTION_MACRO /* expand to nothing */
int sigsetjmp AVOID_FUNCTION_MACRO (sigjmp_buf env, int savesigs) {
    log_fatal_error("Can't call sigsetjmp via pointer, its a macro!");
    abort();
}
#endif

これsigsetjmpにより、アドレスを取得できる関数が提供されますが、実際に呼び出すことはできません...

于 2013-03-06T17:05:28.793 に答える