2016-06-29 9 views
-1

私はコンパイラの最適化と知っていますが、実際のコードでこの動作がどのように通知されるのか、ms vC++コンパイラが誤ったコードを最適化する

私はこのコードを明らかに

void swap(char *s) 
{ 
    strcpy(s, "nope!"); 
    printf("Result: %s\n", s); 
}; 

void main(){ 
... 
swap("this should segfault"); 
... 
} 

を持って、それがセグメンテーションフォールト必要がありますが、リリースモードでVisual Studioは、ちょうどprintfのをインライン化にそれを軽減します。

これは、後でお尻の中で本当に私を噛むことができるようなものだと思います。ここでは完全酒のため

はここに期待アセンブリ

push offset s  ; "this should segfault" 
call [email protected]@[email protected] ; swap(char *) 

とあるコメントで要求されるように生成されたアセンブリ

push offset s  ; "this should segfault" 
push offset Format ; "Result: %s\n" 
call ds:__imp__printf 

、ここでは、コンパイラオプションですさ

/GS /GL /analyze- /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /Fd"Release\vc120.pdb" /fp:precise /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_LIB" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oy- /Oi /MD /Fa"Release\" /EHsc /nologo /Fo"Release\" /Fp"Release\scratchpad2.pch" 
+0

なぜこのコードがクラッシュすると思いますか?誰かのために 's'の価値について十分な詳細を与えておらず、確かにそれを知っている。それはヌルですか?バッファオーバーフローですか? –

+2

これがセグメンテーションするのはなぜ明らかですか?このコードは、 's'に関するある仮定が成り立っている限り、私にとって有効です。そして、それらが保持しない場合( 's'が書き込み可能な十分なバッファを指していないため)、コードは未定義の振る舞いを示し、コンパイラは自由に結果を生成します。 「動作するように見える」は、未定義の動作の可能性のある表現の1つです。 –

+0

@ igor fair。コンパイルで生成されたアセンブリと同様にフォールトになるサンプルコールが追加されました – jhbh

答えて

1

挙動VC++ 2013および2015でここで確認されました。@ IgorTandetnikのコメントはcorですrect。コードにはUB(未定義の動作)が表示され、ではなく、がクラッシュする可能性があります。

しかし、VC++は、(私が思う)C++以降では推奨されていない文字列リテラルから非constのcharポインタへの変換を許可するときに(少なくとも) 0x - Why can a string literal be implicitly converted to char* only in certain case?およびWhy is passing a string literal into a char* argument only sometimes a compiler error?を参照してください。あなたはそれについてhttps://connect.microsoft.com/visualstudioにバグレポートを提出することを検討するかもしれません。

は、私は、そのコンパイラの最適化を行うには知っているが、私は実際のコードでこの動作を通知していますことを確認する方法/なぜ、どのように本当の深いダイビングを探しています。

質問の後半部分には回答がありません。

how/whyについては、intrinsicに読み取り専用の宛先を指定して最適化すると、strcpyの問題が発生するようです。最終的にはstrcpy全体が黙ってスキップされるので、実際にはむしろ奇妙な動作です。

  • swap#pragma function(strcpy)を追加すると、それは常にクラッシュします。

  • 呼び出しコードをchar z[] = "this should segfault"; swap(z);に変更すると、UB係数が削除され、常に有効になります。


[EDIT]  バック how to ensure i am notified of this behaviour in real code部分に行くと、VC++までコンパイル警告やエラーを義務付けて、明示的に const char *過負荷を提供することにより、それを回避することができ、次の。 VC++ 2013と2015の両方で再び確認しました。

#include <string.h> 
#include <stdio.h> 

#pragma intrinsic(strcpy) 

static void swap(char *s) 
{ 
    strcpy(s, "nope!"); 
    printf("OK: %s\n", s); 
}; 

static void swap(const char *s) 
{ 
    printf("No: %s?\n", s); 
}; 

void main() 
{ 
    char z[] = "this should segfault"; 
    swap(z);      // prints 'OK: nope!' 
    swap("this should segfault"); // prints 'No: this should segfault?' 
} 
関連する問題