VC6でconst intが変な値になる?

[戻る]
え〜いち 2008/02/05(火) 13:40:09
あるライブラリがコンパイルした環境によって返す値が異なって困っていました
原因は、VC++6.0のサービスパックが古い(SP4以降だと正しく動くようです)と起こるよ
うです

const int data = 65535 * 0.2;

としたいときにdataには13107が格納されると思うのですが、デバッカでとめて変数を確
認しても、&dataのアドレスに書かれている数値を見ても、13107になっています
しかし、この変数を使うとおかしなことがおきます
・文字列への変換(CString::Format()を使用)
・ループを回す
for(int i = 0; i < data; i++){
    //13107回ループが回らない
}

これはVC6のバグだと思っていいんですよね?
ちなみに、宣言のconstをとってintで宣言すると期待通りに動作します

たいちう 2008/02/05(火) 14:04:21
> これはVC6のバグだと思っていいんですよね?
> ちなみに、宣言のconstをとってintで宣言すると期待通りに動作します

(多分)SPなしのVC++6ですが再現しません。
再現できるコードを示すことができますか?

BOOL CMy0205Doc::OnNewDocument()
{
    if (!CDocument::OnNewDocument())
        return FALSE;

    const int data = 65535 * 0.2;
    TRACE("data = %d\n", data);

    int count = 0;
    for (int i = 0; i < data; i++)
        count++;
    TRACE("count = %d\n", count);

    CString str;
    str.Format("%d", data);
    TRACE("str = %s\n", str);

    return TRUE;
}

# SPが当たってないことをどうやって確認できたっけ?

PATIO 2008/02/05(火) 14:28:55
ちょっと気になったこと、「13107回ループが回らない」とありますけれど、
では、いったい何回回っているんでしょう?

あと、少なくとも私はそういう現象にあったことは有りません。

ん? 2008/02/05(火) 14:33:29
実際にたいいちろうさんのソースでやってみた。
    data    0x00003333
    count    0x036f03e0
    i    0x036f03e0
ほぉー…。


コンパイル時にワーニングが出てました。
warning C4244: 'initializing' : 'const double' から 'const int' に
変換しました。データが失われているかもしれません。

え〜いち 2008/02/05(火) 15:02:46
>たいちう様

ダイアログベースのアプリを作ってOnInitDialogの中で

    const int data = 65535 * 0.2;
    CString str;
    str.Format("%d", data);
    this->SetDlgItemText(IDC_EDIT1, str);

としてみました。IDC_EDIT1はエディットボックスでとんでもない値が表示されました

また、コンソールアプリで

    const int data2 = 65535 * 0.2;
    int time = 0;
    for(int i = 0; i < data; i++){
        time++;
    }
とやったらtimeに大きな値が入りました

え〜いち 2008/02/05(火) 15:04:51
># SPが当たってないことをどうやって確認できたっけ?

レジストリエディタで
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\6.0

の下にサービスパックがあたっているとServicePacksができていてその中にSPの値が記述
されます

え〜いち 2008/02/05(火) 15:05:36
>PATIO様

値は大きな値なんですが、そのときによって違うので、不定です

ん? 2008/02/05(火) 15:07:01
追記
179:      int count = 0;
00401CCB   mov         dword ptr [ebp-18h],0
180:      for (int i = 0; i < data; i++) {
00401CD2   mov         dword ptr [ebp-1Ch],0
00401CD9   jmp         CBbDlg::OnButton1+64h (00401ce4)
00401CDB   mov         eax,dword ptr [ebp-1Ch]
00401CDE   add         eax,1
00401CE1   mov         dword ptr [ebp-1Ch],eax
00401CE4   cmp         dword ptr [ebp-1Ch],36F03E0h       ←ここ
00401CEB   jge         CBbDlg::OnButton1+78h (00401cf8)
181:          count++;
00401CED   mov         ecx,dword ptr [ebp-18h]
00401CF0   add         ecx,1
00401CF3   mov         dword ptr [ebp-18h],ecx
182:      }
00401CF6   jmp         CBbDlg::OnButton1+5Bh (00401cdb)
183:      TRACE("count = %d\n", count);


混合モードで見ると"ここ"でi値とdata値(=36F03E0h)を比較してますね。

え〜いち 2008/02/05(火) 15:08:52
>ん?様
ワーニングができていることはわかっています
が、65535と0.2の演算はdoubleで行われて、const intにキャストされるので65535*0.2は
整数型で13107なので、13107が格納されることを期待しています

え〜いち 2008/02/05(火) 15:12:46
すいません
コードが間違っていました


  const int data2 = 65535 * 0.2;//data2でなくてdataです
  int time = 0;
  for(int i = 0; i < data; i++){
      time++;
  }

たいちう 2008/02/05(火) 15:14:27
> レジストリエディタで
> HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\6.0
> 
> の下にサービスパックがあたっているとServicePacksができていてその中にSPの値が記述
> されます

ありがとうございます。当方、SP6があたってました。勘違いです。


> ダイアログベースのアプリを作ってOnInitDialogの中で
> ...
> としてみました。IDC_EDIT1はエディットボックスでとんでもない値が表示されました

これは再現しませんでした。


> また、コンソールアプリで
> 
>     const int data2 = 65535 * 0.2;
>     int time = 0;
>     for(int i = 0; i < data; i++){
>         time++;
>     }
> とやったらtimeに大きな値が入りました

これは、data と data2 がありますよね。
実際に試したコードはいかがですか?

# おそらく、SPのせいではなく、この手の勘違いのせいだと思うのですが。
# 冷静に検証してみてください。

え〜いち 2008/02/05(火) 15:14:35
>ん?様
dataはconstなので、36F03E0hのところに00003333hとなっているのが正しい姿だと思って
います

たいちう 2008/02/05(火) 15:27:54
ホントにVCのバグのような気もしてきた。
私の環境(VC6 + SP6)では、ん?さん掲示の部分(+α)は、
次のようになる。

125:      const int data = 65535 * 0.2;
00401973   mov         dword ptr [ebp-1Ch],3333h
126:      TRACE("data = %d\n", data);
0040197A   push        3333h
0040197F   push        offset string "data = %d\n" (00415114)
00401984   call        AfxTrace (00401124)
00401989   add         esp,8
127:
128:      int count = 0;
0040198C   mov         dword ptr [ebp-20h],0
129:      for (int i = 0; i < data; i++)
00401993   mov         dword ptr [ebp-24h],0
0040199A   jmp         CMy0205_2Dlg::OnInitDialog+115h (004019a5)
0040199C   mov         edx,dword ptr [ebp-24h]
0040199F   add         edx,1
004019A2   mov         dword ptr [ebp-24h],edx
004019A5   cmp         dword ptr [ebp-24h],3333h
004019AC   jge         CMy0205_2Dlg::OnInitDialog+129h (004019b9)
130:          count++;
004019AE   mov         eax,dword ptr [ebp-20h]
004019B1   add         eax,1
004019B4   mov         dword ptr [ebp-20h],eax
004019B7   jmp         CMy0205_2Dlg::OnInitDialog+10Ch (0040199c)
131:      TRACE("count = %d\n", count);


const int data = 65535 * 0.2;
を、
const int data = 13107;
や
const int data = 65535 / 5;
にすると、どうなります?

え〜いち 2008/02/05(火) 15:30:27
>たいちう様

>これは、data と data2 がありますよね。
>実際に試したコードはいかがですか?

元コードを修正していたので、正しい情報が提供できなくてすませんでした

># おそらく、SPのせいではなく、この手の勘違いのせいだと思うのですが。
># 冷静に検証してみてください。

現在、数名で同じ確認をしていますが、まず間違いなくSPの問題だと思っています
SPの修正の情報をネットで調べていますが、いまだ見当たらず・・・

え〜いち 2008/02/05(火) 15:39:23
>たいちう様

const int data = 13107;
const int data = 65535 / 5;

どちらも大丈夫です
ただし、
const int data = 65535 / 5.0;

とするとおかしくなります

たいちう 2008/02/05(火) 16:05:21
おそらく、これかな。

http://www.microsoft.com/japan/msdn/vstudio/downloads/sp/vs6fixes.aspx#VisualC

6.3.5.2. Service Pack 3 で修正された問題
コンパイラは、浮動小数値で初期化される const int 変数を正しく初期化しませんでした。

え〜いち 2008/02/05(火) 16:12:26
[[解決]]
>たいちう様

情報ありがとうございます
助かりました

ん? 2008/02/05(火) 16:24:29
>たいちうさん
自身が記載したHN間違ってましたね…済みません。

>え〜いちさん
自身の環境はVC6.0の無印でした。
# 今更ながらですが、SP6にしましたww

古いスレッドには追加発言できません。