●
-fleading-underscore
このオプション,およびその否定のオプションである-fno-leading-underscoreは,オブジェクトファイルの中でCのシンボルが表現される方法を強制的に変更します.古いアセンブラコードとのリンクをサポートします.coff環境やi386用のクロスコンパイルでも使用します.
ターゲットすべてに有効であるわけではないので,理解して使わないと混乱を招きます.
Windowsの開発言語であるVisual C++は,アンダースコア付きシンボル名を生成します.よって,Cygwin環境で使用する場合には,Visual C++で作成されたDLLの呼び出しの際に注意しなくてはなりません.
ソースと生成されたコードをリスト1,リスト2に示します.
このようにシンボル名の先頭に_(アンダースコア)が付いています.リスト3に,オプションなしで生成されたソースを示します.
● -fno-common
初期化済みでないグローバル変数をオブジェクトファイル中のbssセクションに割り当てます.
コードと生成されたソースをリスト4〜リスト6に示します.
生成されたアセンブラ上で疑似命令である.bssでセクションの指定がされています(リスト6).
こちらのアセンブラソース上では共有領域をメモリに確保する疑似命令である.commが使われています.
また,二つの異なるコンパイル単位の中でexternを使わずに同一のグローバル変数が宣言されている場合,リンク時エラーを発生させることができます.
● -fno-gnu-linker
GNUのリンカを使用しないときにこのオプションを指定します.注意すべきなのは,このオプションを指定すると,C++のコンストラクタやデコンストラクタをGNUのリンカで使われる形で出力しない点です.
● -fnon-call-exceptions
このオプションに関してはC++を説明する際に扱います.throw exceptionsをトラップするために使います.
● -funwind-tables
C++で作成されたモジュールとリンクし,なおかつ例外処理を行っている場合,このオプションを指定することが必要になります.
使用している関数に対してフレーム解放のための情報が生成されます.
-fexceptionsとの違いは,ライブラリ関数に対してはその情報が生成されないことです.
ただし,CやC++のすべてのモジュールがGCCで作成された場合,それを意識しなくても良いはずです.そして,まったく別の環境で作成されたオブジェクトファイルとリンクさせる場合にも,その言語環境で同じような機能を用意しているかもしれません.
コードと生成されたソースをリスト7〜リスト9に示します.このようにフレーム解放のための情報が生成されます.
● -fasynchronous-unwind-tables
フレーム解放のための情報をdwarf2フォーマットで生成することができます.もちろん,ターゲット側がdwarf2フォーマットに対応していることが前提となります.
そして,非同期イベントが発生したときにフレームの巻き戻しを行うことが可能になります.
基本的に,-funwind-tablesと同様の機能です.
● -finstrument-functions
このオプションを付けると,関数の出口と入口でトレース用の関数を呼び出す命令を付加します.関数の入口では,
void __cyg_profile_func_enter (
void *this_fn,void *call_site);
以上を,関数の出口では,
void __cyg_profile_func_exit (
void *this_fn,void *call_site0);
以上を,それぞれ呼び出します.
この関数をトレースに利用することができます.しかし,単純なトレースならばGDBを使ったほうが早いと思います.
コードをリスト10に示します.
生成されたソースを後で示しますが,付加された関数,
void __cyg_profile_func_enter(
void *this_fn,void *call_site)
以上が関数の入り口で呼び出されるので,次のように情報を取得できます.
当該関数のアドレスを標準出力に,
printf("%p\n",this_fn);
以上を,当該関数から戻った箇所を標準出力に,
printf("%p\n",call_site);
以上を,それぞれ出力しています.
コンパイルと実行の結果を次に示します.
$ gcc test198.c -o test198
-finstrument-functions -Xlinker
-Map -Xlinker test198.map
上のようにコンパイルすると,マップファイル(リスト11)が出力され,実行結果は次のようになります.
$ ./test198
0x80483d4
0x42015574
0x8048441
0x80483fd
100
0x804847b
0x8048412
0x80484ca
0x804849a
300
200
$
また,次のようにコマンドを入力するとtest198.txt(リスト12)に実行形式の逆アセンブラリストが出力されます.
$ objdump -d a.out > test198.txt
オブジェクトファイルのシンボルを表示したい場合は次のようにコマンドを入力します.test198.lst(リスト13)に出力されます.
$ nm -a test198 > test198.lst
実行結果とtest198.txtを付き合わせると次のことがわかります.
0x80483d4 関数mainのアドレス
0x42015574 戻った先の次の命令
0x8048441 関数test1のアドレス
0x80483fd 戻った先の次の命令
100 main中での最初のprintfの結果
(関数test1から抜けた)
0x804847b 関数test2のアドレス
0x8048412 戻った先の次の命令
0x80484ca 関数test21のアドレス
0x804849a 戻った先の次の命令
300 関数test2中でのprintfの結果
(関数test21から抜けた)
200 関数main中での2番目のprintfの結果
(関数test2から抜けた)
このようにトレースに使うことができます.関数の作り方によっては実行時間の計測も可能です.リスト10から生成されたソースをリスト14に示します.
次のような行が付加されています.
call __cyg_profile_func_enter
call __cyg_profile_func_exit
なお,比較対象として,オプションなしで生成したソースをリスト15に示します.
● -fshort-wchar
wchar_t型は通常4バイトです.しかし,Windowsではwchar_t型をshort unsigned int(2バイト)として扱わなければなりません.このオプションを指定すると,wchar_t型を2バイトとして扱います.CygwinなどでWindows環境とリンクする場合,またはWINEなどのWindowsエミュレータを使う場合に使用します.
コードと生成されたソースをリスト16,リスト17に示します.また,オプションなしでコンパイルした結果をリスト18に示します.
リスト17からわかるように,変数dataは内部で2バイトとして扱われています.
そして,変数dataは内部で4バイトとして扱われています.
コンパイルと実行の結果を次に示します.
$ gcc test199.c
$ ./a.out
wchar_tのサイズは4です
$ gcc test199.c -fshort-wchar
$ ./a.out
wchar_tのサイズは2です