GCC の __atribute__ キーワード
書籍「C/C++セキュアコーディング」を読んでたら書いてあったので, テスト.
GCC依存(だよね?).
詳細は, GCCのinfoを読むしかないのかな.
関数は, before, main, afterの順で実行されるハズ.
#include<stdio.h> void before( void ) __attribute__ ((constructor)); void after( void ) __attribute__ ((destructor)); int main( int argc, char *argv[] ) { puts( "main" ); return 0; } void before( void ){ puts( "before" ); } void after( void ){ puts( "after" ); }
このプログラムを, コンパイル, そして, 実行
[khiker@khlin001 ~/<1>c/gcc]$ ./test_attribute1 before main after
ちゃんと予定通りの動作をしました.
GCCでは, 関数に属性を指定することができる.
やり方は, __attribute__キーワードにつづいて, 二重の丸括弧で囲んで属性名を指定する.
今回指定したものは, constructor と destructor.
constructorは, mainの実行前に.
descructorは, mainの処理後, もしくは, exit が呼ばれた後に実行される.
constructor や destructor を指定した関数が複数あるとどうなるか実験.
#include<stdio.h> void before1( void ) __attribute__ ((constructor)); void before2( void ) __attribute__ ((constructor)); void after1( void ) __attribute__ ((destructor)); void after2( void ) __attribute__ ((destructor)); int main( int argc, char *argv[] ) { puts( "main" ); return 0; } void before1( void ){ puts( "before1" ); } void before2( void ){ puts( "before2" ); } void after1( void ){ puts( "after1" ); } void after2( void ){ puts( "after2" ); }
こんなつまんない例を作ってみた.
以下, コンパイルと実行.
[khiker@khlin001 ~/<1>c/gcc]$ gcc test_attribute2.c -o test_attribute2 -Wall [khiker@khlin001 ~/<1>c/gcc]$ ./test_attribute2 before2 before1 main after1 after2 [khiker@khlin001 ~/<1>c/gcc]$ ./test_attribute2 before2 before1 main after1 after2 [khiker@khlin001 ~/<1>c/gcc]$ ./test_attribute2 before2 before1 main after1 after2
何度やっても同じ順序で実行されるということは, 何かルールがあるのかな.
日本語版のinfoを簡単に(ホント簡単に)読んでみたけど, 特に書いてないようだから, さらに実験.
宣言の順番を変えてみる.
これを,
void before1( void ) __attribute__ ((constructor)); void before2( void ) __attribute__ ((constructor)); void after1( void ) __attribute__ ((destructor)); void after2( void ) __attribute__ ((destructor));
こうする.
void before2( void ) __attribute__ ((constructor)); void before1( void ) __attribute__ ((constructor)); void after2( void ) __attribute__ ((destructor)); void after1( void ) __attribute__ ((destructor));
結果.
[khiker@khlin001 ~/<1>c/gcc]$ gcc test_attribute2.c -o test_attribute2 -Wall [khiker@khlin001 ~/<1>c/gcc]$ ./test_attribute2 before2 before1 main after1 after2
変化なし.
じゃあ, 関数実装部分の順番を変えてみようかな.
これを,
void before1( void ){ puts( "before1" ); } void before2( void ){ puts( "before2" ); } void after1( void ){ puts( "after1" ); } void after2( void ){ puts( "after2" ); }
こうする.
void before2( void ){ puts( "before2" ); } void before1( void ){ puts( "before1" ); } void after2( void ){ puts( "after2" ); } void after1( void ){ puts( "after1" ); }
結果.
[khiker@khlin001 ~/<1>c/gcc]$ gcc test_attribute2.c -o test_attribute2 -Wall [khiker@khlin001 ~/<1>c/gcc]$ ./test_attribute2 before1 before2 main after2 after1
見事に変化.
constructorは, 上から順番にスタックに積んでその順に実行してるってことなのかな.
before2, before1と積む. before2が下. よって, before1から.
んで, destructorは, キューってこと?
よく分からん. 3個以上は, 実験してないからどうなるか分かんないし.
まあ, 通常は, 2つ以上 constructor や destructor 属性を宣言すべきじゃないよね.
混乱するし.
これは, 終了時にメッセージだしたりとか,
結構色々と使えそうな気がする.
良さそう.
他のキーワードもまた調べてみるか.