渡されたメモリバッファが二度と使用されないことがわかっている場合、コンパイラは呼び出しを自由に削除できることをここで読みました。memset
そんなことがあるものか?(コア言語の観点からは)memset
単なる通常の関数であり、コンパイラーには、その内部で何が起こっても副作用がないと想定する権利はないように思われます。
リンクされた記事では、Visual C++10がどのように削除されたかを示していますmemset
。Microsoftコンパイラが標準への準拠をリードしていないことを知っているので、質問します-それは標準に準拠しているのですか、それとも単なるmsvc-ismですか?標準に従っている場合は、詳しく説明してください;)
編集: @Cubbi
次のコード:
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);
}
行付きのmingwの下でコンパイル:
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
宣言にこの属性を持っていないため、何があっても組み立て-私が期待するように。これを調査する必要があります。