私はhereを読んだことがあります。合格したメモリバッファが決して再び使用されないことが分かっていれば、コンパイラはmemset
への呼び出しを自由に削除できます。そんなことがあるものか? memset
はちょうど普通の関数であり、コンパイラは内部で何が起こったとしても副作用がないと想定する権利はないと私には思われます(コア言語の観点から)。`memset`関数呼び出しをコンパイラで削除できますか?
linked articleには、Visual C++ 10がどのようにしてmemset
を削除したかが示されています。マイクロソフトのコンパイラは標準コンプライアンスをリードしていないことを知っています。標準に準拠しているのですか、それともmsvc-ismですか?それは標準に従ってだ場合は、手の込んだしてください;)
EDIT: @Cubbi
次のコード:行とMinGWの下コンパイル
void testIt(){
char foo[1234];
for (int i=0; i<1233; i++){
foo[i] = rand()%('Z'-'A'+1)+'A';
}
foo[1233]=0;
printf(foo);
memset(foo, 0, 1234);
}
:
g++ -c -O2 -frtti -fexceptions -mthreads -Wall -DUNICODE -o main.o main.cpp
g++ -Wl,-s -Wl,-subsystem,console -mthreads -o main.exe main.o
objdump -d -M intel -S main.exe > dump.asm
は出力を与えました:
4013b0: 55 push ebp
4013b1: 89 e5 mov ebp,esp
4013b3: 57 push edi
4013b4: 56 push esi
4013b5: 53 push ebx
4013b6: 81 ec fc 04 00 00 sub esp,0x4fc
4013bc: 31 db xor ebx,ebx
4013be: 8d b5 16 fb ff ff lea esi,[ebp-0x4ea]
4013c4: bf 1a 00 00 00 mov edi,0x1a
4013c9: 8d 76 00 lea esi,[esi+0x0]
4013cc: e8 6f 02 00 00 call 0x401640
4013d1: 99 cdq
4013d2: f7 ff idiv edi
4013d4: 83 c2 41 add edx,0x41
4013d7: 88 14 1e mov BYTE PTR [esi+ebx*1],dl
4013da: 43 inc ebx
4013db: 81 fb d1 04 00 00 cmp ebx,0x4d1
4013e1: 75 e9 jne 0x4013cc
4013e3: c6 45 e7 00 mov BYTE PTR [ebp-0x19],0x0
4013e7: 89 34 24 mov DWORD PTR [esp],esi
4013ea: e8 59 02 00 00 call 0x401648
4013ef: 81 c4 fc 04 00 00 add esp,0x4fc
4013f5: 5b pop ebx
4013f6: 5e pop esi
4013f7: 5f pop edi
4013f8: c9 leave
4013f9: c3 ret
行4013eaにはmemset呼び出しがあるので、mingwはそれを削除していません。 mingwはWindowsスキンのGCCですから、GCCも同じことをやっていると思います。私はLinuxに再起動するときにチェックします。
このようなコンパイラを見つけるのにまだ問題がありますか?
EDIT2:私はちょうどGCCの__attribute__ ((pure))
知った
。コンパイラがmemsetについて特別なことを知っているわけではなく、それをエリートするのではなく、ヘッダーにも許されています - それを使用するプログラマも見なければなりません;)私のmingwはmemset
宣言にこの属性を持たないので、私が期待しているように、何に関係なくアセンブリ。私はこれを調べなければならないでしょう。
しかし、 'memset()'は通常の関数ではありません。コンパイラは*副作用がないことを知っているので、しばしば特別な扱いを受ける。 – Mysticial
このような場合にmemsetを排除しないコンパイラを見つけるのが難しいです。 – Cubbi
@Mysticialそれは答えになるだろう。 –