- 締切済み
__attribute__(warning)
gccの__attribute__((warning("message")))の具体的なサンプル(使い方)を教えてもらえないでしょうか?
- みんなの回答 (2)
- 専門家の回答
みんなの回答
- akinomyoga
- ベストアンサー率85% (100/117)
> gccの拡張機能ですが、ここまでするの?って、素人目にですが、呪文のような訳の分からない属性があったりして・・・。akinomyogaさん、このあたりどのように思われますか? もしご意見ありましたらおうかがいできればと幸いです。 基本的に GCC の「拡張」に過ぎないので、多くの属性はアプリケーションコード (ユーザーコード) で使う様な代物ではないと思います。移植性がなくなります (使っても、他のコンパイラでコンパイルできません。或いは #ifdef の嵐になって可読性を損ねます)。中には aligned だとか、あるいは、処理系の都合上指定する必要があるなどで有用な物もありますが、そういう属性は全体からすると極々一部である様に思います。 思うに、多くの訳の分からない属性は GCC に附属してくる標準ライブラリ実装 (glibc や libstdc++ など) の為に作成されたのではないかと思います。glibc や libstdc++ は殆ど GCC の一部の様な物 (といったら過言?) で、GCC と共に使う事が想定されているので遠慮無く GCC 拡張を使えます。そして GCC と共に開発されているので、glibc/libstdc++ をより充実する上で C/C++ 言語のレベルで実現できない事があれば、(汎用性のない機能でも) GCC の方にその機能を「拡張」として追加できてしまう訳です。 例えば「glibc や libstdc++ 並に親切なライブラリを作って皆に配布しよう」などと考えるのでない限りは、多くの「訳の分からない属性」を理解する必要などないのではないでしょうか。
- akinomyoga
- ベストアンサー率85% (100/117)
ちょっと検索してみただけなので、参考になるか分かりませんが。 http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html の説明には、 コンパイル時のプログラム(中の値)のチェックに用いられ、「最適化を通しても呼出が削除されなかった時に」警告が出力される。インライン関数や __builtin_constant_p と一緒に使う。 的な事が書かれています。 ★例えば http://mkosaki.blog46.fc2.com/blog-entry-1229.html では、関数の引数の静的なチェックをする時の使い方が説明されています。 http://www.videolan.org/developers/vlc/include/vlc_threads.h では、check_delay というマクロが定義されていて、そのマクロから条件付で __attribute__ の設定された関数が呼ばれています。ソースコードそのままですが、使い方は、個人的には分かりやすいと思いました。 ★基本的には void some_function_with_warning_attribute() __attribute__((warning("message"))); if( "静的に (コンパイル時に) 値のチェックが可能ならば" ) if( "満たしているべき条件が不成立ならば" ) some_function_with_warning_attribute(); という形で使われる様子(?)。 "静的に値のチェックが可能" かどうかは、コンパイラの組み込み関数 (__builtin_~) を使えば良いです。このコードを解釈する時に重要なのが「最適化を施しても呼出が削除されなかった時に」警告が出力されるという事です。値のチェックが静的に出来なかったり、条件が満たされている場合には some_function_with_warning_attribute() は決して呼び出されないので、最適化によって呼出自体が削除されて警告は出力されません。 some_function_with_warning_attribute() を直接呼び出して使う物だと思ってしまうと「呼び出してはいけない関数」をそもそも定義する意味が分かりませんが、(廃止された関数には __attribute__((deprecated)) を使えばよい訳ですし。) これを異常検査するコードから間接的に呼び出す為の関数と思えば納得がいきます。 # しかしその為ならば、__builtin_generate_compile_time_warning(const char* msg) 的な関数を用意して、以下の様にした方が分かりやすい気もします…。 if( "静的に (コンパイル時に) 値のチェックが可能ならば" ) if( "満たしているべき条件が不成立ならば" ) __builtin_generate_compile_time_warning("message"); # わざわざ __attribute__((warning)) を用意する理由は、あるとは思いますがよくわかりません。文字列定数 "message" をシンボル some_function_with_warning_attribute に紐付けて管理できるからとかですかね?
お礼
ご回答ありがとうございます。教えて頂いた内容で私なりの理解をまとめさせていただきました。 下記サンプルでは、test1()/test()もtest()をコールしていますが、コンパイル時test()で警告をだしています。 #include "stdio.h" void test1() __attribute__ ((alias("test"))); void test() __attribute__((warning("12345"))); void main() { test1(); test(); } void test() { printf("67890\n"); } [root@localhost]# gcc a.c a.c: 関数 ‘main’ 内: a.c:9:6: 警告: call to ‘test’ declared with attribute warning: 12345 [デフォルトで有効] [root@localhost]# ./a.out 67890 67890 定数での処理する場合、コンパイル時にstrcpy等でバッファサイズチェックの判断できて問題がある場合、コンパイラで処理する定数を無理やり変更したり(実装依存と言うことでしょうが)、変更した旨のコンパイラーのメッセージと言う事なのですね。 p/s gccの拡張機能ですが、ここまでするの?って、素人目にですが、呪文のような訳の分からない属性があったりして・・・。akinomyogaさん、このあたりどのように思われますか? もしご意見ありましたらおうかがいできればと幸いです。