2017-01-31 5 views
1

私は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を利用することができ

+0

公式マクロのチェック:

char* check_error(int result, char* buffer, int err) { if(result) sprintf(buffer, "unknown error: %d", err); return buffer; } char* check_error(char* result, char*, int) { return result; } 

としては、使用中に、条件付きコンパイルを取り除きます)は '(_POSIX_C_SOURCE> = 200112L || _XOPEN_SOURCE> = 600)&&!です。 _GNU_SOURCE'をPOSIXバージョンが提供されている場合は真、そうでない場合はGNUバージョンが提供されます。つまり、GNUバージョンが提供されていることを確認するのに十分なチェックが必要であり、Alpine LinuxのCライブラリはバグがあるか、古くなっているようです。 –

+0

独自の関数でラップします。いずれかのバリアントを使用するのに十分な柔軟性を持たせます。 –

+0

@ n.m。あなたは精緻化できますか?これはすでに関数にラップされています... – selbie

答えて

5

++関数のオーバーロード:(あなたにリンクしてマニュアルページによると

char buffer[1000]; 
buffer[0] = '\0'; 
char* msg = check_error(strerror_r(err, buffer, sizeof buffer), buffer, err); 
LogToFile(msg); 
+0

ありがとうございます。なぜ私はこれについて自分自身を考えなかったのか分かりません。今はとても分かりやすいでしょう。 – selbie

関連する問題