振る舞う[更新] 2016年7月2日標準機能をオーバーライドすると、予想外に
main.cの
#include <stdio.h>
#include <string.h>
size_t strlen(const char *str) {
printf("%s\n", str);
return 99;
}
int main() {
const char *str = "AAA";
size_t a = strlen(str);
strlen(str);
size_t b = strlen("BBB");
return 0;
}
は、予想出力は、メインメイン-o GCC -O0でコンパイル
AAA
AAA
BBB
あります。 c:
AAA
コンパイルウィットH GCC -O3 -o主main.cの
AAA
AAA
フラグと対応するASMコード-O0
000000000040057c <main>:
40057c: 55 push %rbp
40057d: 48 89 e5 mov %rsp,%rbp
400580: 48 83 ec 20 sub $0x20,%rsp
400584: 48 c7 45 e8 34 06 40 movq $0x400634,-0x18(%rbp)
40058b: 00
40058c: 48 8b 45 e8 mov -0x18(%rbp),%rax
400590: 48 89 c7 mov %rax,%rdi
400593: e8 c5 ff ff ff callq 40055d <strlen>
400598: 48 89 45 f0 mov %rax,-0x10(%rbp)
40059c: 48 c7 45 f8 03 00 00 movq $0x3,-0x8(%rbp)
4005a3: 00
4005a4: b8 00 00 00 00 mov $0x0,%eax
4005a9: c9 leaveq
4005aa: c3 retq
4005ab: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
と-O3有する:フラグ-O0で
0000000000400470 <main>:
400470: 48 83 ec 08 sub $0x8,%rsp
400474: bf 24 06 40 00 mov $0x400624,%edi
400479: e8 c2 ff ff ff callq 400440 <[email protected]>
40047e: bf 24 06 40 00 mov $0x400624,%edi
400483: e8 b8 ff ff ff callq 400440 <[email protected]>
400488: 31 c0 xor %eax,%eax
40048a: 48 83 c4 08 add $0x8,%rsp
40048e: c3 retq
、なぜstrlenへの2回目と3回目の呼び出しが、ユーザー定義のstrlenを呼び出さなかったのでしょうか?
そして-O3では、なぜstrlenへの3番目の呼び出しが最適化されていますか?
おそらく、コンパイラが冗長呼び出しを最適化したためですが、それは実装に副作用があると考えると少し奇妙です。 'strlen()'のようなよく知られている関数をどこまで使うのかは不明です。デバッガでコードをシングルステップ実行します。 – unwind
これはgccと仮定し、 '-fno-optimize-strlen'を使ってコンパイルしてみてください – tofro
関数の名前を' my_strlen'に変更して何が起こるかを見てください。そして関数実装で 'extern'キーワードを削除します。 – LPs