8

C++ Win32 コンソール アプリケーションを実行している Visual Studio 2005 を使用して、非常に重大なエラーに遭遇しました。次のプロジェクト プロパティを使用して、以下のコード (簡略化) を実行すると、問題が発生します: C++|最適化|最適化|/O2 (または /O1、または /Ox)、C++|最適化|プログラム全体の最適化|/GL、リンカー|最適化|/ltcg

    #include "stdafx.h"
    #include <iostream>
    using namespace std;
    const int MAXVAL=10;
    class MyClass
    {
    private:
      int p;
      bool isGood;
    public:
      int SetUp(int val);
    };
    int MyClass::SetUp(int val)
    {
      isGood = true;
      if (MAXVAL<val)
      {
        int wait;
        cerr<<"ERROR, "<<MAXVAL<<"<"<<val<<endl;
        cin>>wait;
        //exit(1);      //for x64 uncomment, for win32 leave commented
      }
      if (isGood) p=4;
      return 1;
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
      int wait=0, setupVal1=10, setupVal2=12;
      MyClass classInstance1;
      MyClass classInstance2;
      if (MAXVAL>=setupVal1) classInstance1.SetUp(setupVal1);
      if (MAXVAL>setupVal2) classInstance2.SetUp(setupVal2);
      cerr<<"exit, enter value to terminate\n";
      cin>>wait;
      return 0;
    }

出力は、値 10 が値 10 より小さいことを示しています。/O2 の設定を /Od に変更すると問題が解決することは既にわかっていますが (/O2 の一部である /Og を設定すると問題が発生します)、実際には実行時間が遅くなります。また、コードを少し変更することで解決できますが、コードが信頼できるかどうかはわかりません。私はVisual Studio 2005プロフェッショナル(バージョン8.0.50727.867)、OS Windows 7を使用しています。私の質問は、誰かがVisual Studio 2005を使用してこのエラーを再現できるかどうかです(私はすでにVS 2010を試しましたが、問題ありません)。ここで起こる?新しいバージョンでこの問題が解決されたと思いますか (VS 2012 の購入を検討しています) ありがとうございます

4

1 に答える 1

3

例を大幅に減らしても、同じ問題が発生する可能性があります! 2 つのインスタンスは必要なく、他のローカル変数やメンバー変数も必要ありません。また、ハードコードすることもできますMAXVAL

問題を「解決」するものの簡単な要約:

  • MAXVAL非定数にするint
  • setupVal210未満の値に設定
  • 驚くべきことに、条件10<valval>10 !!!に変更します。

問題を再現するための最小バージョンは次のとおりです。

#include "stdafx.h"
#include <iostream>
using namespace std;

class MyClass
{
public:
    int SetUp(int val);
};

int MyClass::SetUp(int val)
{
    if (10<val)
        cout<<10<<"<"<<val<<endl;
    return 1;
}

int _tmain(int argc, _TCHAR* argv[])
{
    int setupVal1=10, setupVal2=12;
    MyClass classInstance;

    classInstance.SetUp(setupVal1);
    classInstance.SetUp(setupVal2);

    cin.get();
    return 0;
}

逆アセンブルでわかるように、問題は、コンパイラが10<valを常に true と見なし、チェックを省略していることです。

_TEXT   SEGMENT
?SetUp@MyClass@@QAEHH@Z PROC                ; MyClass::SetUp
; _val$ = ecx

; 16   :    if (10<val)
; 17   :        cout<<10<<"<"<<val<<endl;

    mov eax, DWORD PTR __imp_?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z
    push    eax
    push    ecx
    mov ecx, DWORD PTR __imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A
    push    10                  ; 0000000aH
    call    DWORD PTR __imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
    push    eax
    call    ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z ; std::operator<<<std::char_traits<char> >
    add esp, 4
    mov ecx, eax
    call    DWORD PTR __imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
    mov ecx, eax
    call    DWORD PTR __imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z

; 18   :    return 1;

    mov eax, 1

; 19   : }
于 2013-09-18T13:29:35.023 に答える