私はstrerror_rをロギングヘルパー機能で使用しています。マニュアルページで説明しているように、この関数には2つのバージョンがあります。 POSIXバージョンはintを返します。 GNUバージョンは文字列(char *)を返します。このようアルパインのLinuxでstrerror_rが間違って宣言されました
、私のC++コードをよりポータブルになるように、私はこのようなコードのブロックを有する:上記のコードブロックで
char buffer[1000];
int size = 1000;
int result = 0;
char* msg = buffer;
buffer[0] = '\0';
#ifdef _GNU_SOURCE
msg = strerror_r(err, buffer, size);
#else
result = strerror_r(err, buffer, size);
if (result != 0)
{
sprintf(buffer, "unknown error: %d", err);
}
#endif
LogToFile(msg);
を、それが存在に応じstrerror_r
のバージョンのいずれかを使用します_GNU_SOURCE
です。これは、libstdC++が必要とするため、g ++で常に設定されています。 MacやUnixの他のバリエーションでは、POSIXバージョンを使用します。
このコードは、今日までずっと長い間、うまくいきました。ユーザーがAlpine Linuxの私のコードをコンパイルしようとすると、この行にマップstrerror_r
main.cpp:16:21 error: invalid conversion from 'int' to 'char*' [-fpermissive]
を使用して行に、今日、このコンパイラエラーを報告しました:このプラットフォーム上で/usr/include/string.h
にピークを取る
#ifdef _GNU_SOURCE
msg = strerror_r(err, buffer, size);
が明らかに
#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
|| defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
|| defined(_BSD_SOURCE)
...
int strerror_r (int, char *, size_t);
...
#endif
どのようなコンパイラ環境が使用されていても、 strerror_rのnは、intを返すPOSIXバージョンです。エラーが発生した理由を説明します。
手動で#undef _GNU_SOURCE
を送信したり、ソースを変更したりする必要がなく、コードを移植可能な状態に戻すにはどうすればよいですか? _GNU_SOURCEをグローバルに定義していないのは、これがC++(そして前述のようにlibstdC++で必要とされる)であるため、非スターターではない可能性があります。私はテストできる別のマクロコンビネーションがあるかどうかを確認しようとしていますが、私は何も明らかにできません。あなたがCを利用することができ
公式マクロのチェック:
としては、使用中に、条件付きコンパイルを取り除きます)は '(_POSIX_C_SOURCE> = 200112L || _XOPEN_SOURCE> = 600)&&!です。 _GNU_SOURCE'をPOSIXバージョンが提供されている場合は真、そうでない場合はGNUバージョンが提供されます。つまり、GNUバージョンが提供されていることを確認するのに十分なチェックが必要であり、Alpine LinuxのCライブラリはバグがあるか、古くなっているようです。 –
独自の関数でラップします。いずれかのバリアントを使用するのに十分な柔軟性を持たせます。 –
@ n.m。あなたは精緻化できますか?これはすでに関数にラップされています... – selbie