volatileとgcc
追加した機能が元で最適化の問題をを踏んだ。
何故か呼ばれるはずの関数が飛ばされるので何でかと思ったら
volatileつけ忘れが原因。
どの程度最適化掛けると飛ばされるようになるのか気になったのでサンプル書いて実験。
踏んだプログラムはthread使ってたけど、スコープ外で変更掛かるから同じだろうと
思いサンプルは単純化。
テストコード
int flag_g; int main(int argc,char ** argv){ flag_g = 0; if(flag_g) printf("HOGE\n"); return 0; } int func(){ flag_g = 1; }
gcc -O0 の objdump
000103dc <main>: 103dc: 9d e3 bf 98 save %sp, -104, %sp 103e0: f0 27 a0 44 st %i0, [ %fp + 0x44 ] 103e4: f2 27 a0 48 st %i1, [ %fp + 0x48 ] 103e8: 03 00 00 81 sethi %hi(0x20400), %g1 103ec: 82 10 62 ec or %g1, 0x2ec, %g1 ! 206ec <flag_g> 103f0: c0 20 40 00 clr [ %g1 ] 103f4: 03 00 00 81 sethi %hi(0x20400), %g1 103f8: 82 10 62 ec or %g1, 0x2ec, %g1 ! 206ec <flag_g> 103fc: c2 00 40 00 ld [ %g1 ], %g1 10400: 80 a0 60 00 cmp %g1, 0 10404: 02 80 00 06 be 1041c <main+0x40> 10408: 01 00 00 00 nop 1040c: 03 00 00 41 sethi %hi(0x10400), %g1 10410: 90 10 61 90 or %g1, 0x190, %o0 ! 10590 <_IO_stdin_used+0x8> 10414: 40 00 40 af call 206d0 <printf@plt> 10418: 01 00 00 00 nop 1041c: 82 10 20 00 clr %g1 ! 0 <_init-0x10284> 10420: b0 10 00 01 mov %g1, %i0 10424: 81 c7 e0 08 ret 10428: 81 e8 00 00 restore
gcc -O1 の objdump
000103b4 <main>: 103b4: 03 00 00 81 sethi %hi(0x20400), %g1 103b8: c0 20 62 58 clr [ %g1 + 0x258 ] ! 20658 <flag_g> 103bc: 81 c3 e0 08 retl 103c0: 90 10 20 00 clr %o0
gcc -O1 の objdump (flag_gにvolatile付与)
000103ec <main>: 103ec: 9d e3 bf 98 save %sp, -104, %sp 103f0: 05 00 00 81 sethi %hi(0x20400), %g2 103f4: c0 20 a2 dc clr [ %g2 + 0x2dc ] ! 206dc <flag_g> 103f8: c6 00 a2 dc ld [ %g2 + 0x2dc ], %g3 103fc: 80 a0 e0 00 cmp %g3, 0 10400: 02 80 00 05 be 10414 <main+0x28> 10404: b0 10 20 00 clr %i0 10408: 03 00 00 41 sethi %hi(0x10400), %g1 1040c: 40 00 40 aa call 206b4 <puts@plt> 10410: 90 10 61 78 or %g1, 0x178, %o0 ! 10578 <_IO_stdin_used+0x8> 10414: 81 c7 e0 08 ret 10418: 81 e8 00 00 restore
gcc -O1の時点で既に関数呼び出し箇所が跡形もなくなっている。
今回問題追っかけていて使ったけど、gdbのtuiモードは意外に便利だった。
registerとassemblerウィンドウ出しながらステップ実行とか。