Win2000 .Net2003 VC++
下記プログラムをリリース版(最適化:実行速度)で実行すると●の部分で落ちてしまいます。
コンパイルの不具合でしょうか?
アセンブリ言語がわからない為原因がわかりません。
元のプログラムから現象が発生する部分を削り取っている為
意味の無い処理もありますが必要な処理なので削除は出来ません。
原因を特定したいのでお力をお貸しください。
よろしくお願いします。
{
CString fname = _T(C:\\test.txt); //
CString dpath = _T(C:\\);
CString dname_l1 = _T(test1.txt); //
CString dname_l2 = _T(test2.txt); //
CFile file;
unsigned long fsize = 11;
file.Open(fname, CFile::modeCreate|CFile::modeWrite);
if(file.m_hFile!=CFile::hFileNull){
fname = dpath + dname_l1;
fsize = _byteswap_ulong(0xFFFFFFF0); //
file.Write(&fsize, sizeof(fsize));
// 省略
fname = dpath + dname_l2; // ●
fsize = _byteswap_ulong(0xFFFFFFF0); //
file.Write(&fsize, sizeof(fsize));
// 省略
file.Close();
}
}
この提示範囲ではないところに、原因があるのでは?
(不定値か、メモリ破壊あたり?)
全部さらすとか、もう少し情報が必要かと。
{
CString fname = _T(C:\\test.txt); //
CString dpath = _T(C:\\);
CString dname_l1 = _T(test1.txt); //
CString dname_l2 = _T(test2.txt); //
fname = dpath + dname_l1;
fname = dpath + dname_l2; // ●
}
提示されたソースの該当箇所だけ抜き取ると、こういう事だよね。
怪しい原因となる様な箇所が見受けられない。
Banさんの指摘通りでしょうね。
Banさんレスありがとうございます。
>全部さらすとか、もう少し情報が必要かと。
元のプログラムからの省略であって、テストプログラムでは
上記コードが全てです。(省略はただのコメントです。)
現象だしの手順的には下記の通りです。
1:新規作成でMFCアプリケーションのダイアログベースプロジェクトを作ります。
:「ダイアログベース」と「スタティックライブラリでMFCを使用する」を選択します。
2:リソースの追加でボタンを貼り付けます。
3:ボタンクリックの関数内に上記プログラムをコピペします。
4:リリース版でコンパイルして実行すると現象が発生します。
現象だしで1つわかった事があります。
MFCの使用設定が「スタティックライブラリでMFCを使用する」の時に現象が発生し、
「共有DLLを使用する」の時には現象が発生しない様です。
この設定の違いで何か上記プログラムに影響があるのでしょうか?
助言をお願いします。また、他に何かわかりましたら書き込みます。
.....さんレスありがとうございます。
この現象を出すのに該当個所のみを抜き出して実行するだけでは現象が発生しない様です。
_byteswap_ulongの呼び出し、その引き数が0xFFFFFFF0、文字列の結合、ファイルアクセス、
同様の処理を2回呼び出さないと現象が発生しません。
結構シビアな条件でしか現象が発生しない様です。
元のプログラムはこの条件から外すと落ちる場所が変化するので
Banさんの指摘通りどこかを破壊しているようです。
テストプログラムで原因を特定できれば元のプログラムの方も対応できると思いますので
原因の特定をしたいと思っています。よろしくお願いします。
こうゆうことやったことないんで質問ですが、
> fname = dpath + dname_l1;
> fname = dpath + dname_l2; // ●
これは何のために?
有効でないと思うのですが?
連投すみません。
あと、気になったところが、
fnameって一度oepnするときに使ってますね。
一旦fcloseしてから変えないとまずいのでは?
大丈夫ならいいのですが。。。。。。。
ITOさんレスありがとうございます。
>こうゆうことやったことないんで質問ですが、
>> fname = dpath + dname_l1;
>> fname = dpath + dname_l2; // ●
>これは何のために?
>有効でないと思うのですが?
そうですねこれだけでは意味をなさないですね。
質問時に載せたテストプログラムでは現象を出す為の条件となる為処理しています。
元のプログラムでは「// 省略」の部分でファイルアクセスをする為に使用しています。
テストプログラムでは省略しても現象が発生する為「// 省略」としています。
>fnameって一度oepnするときに使ってますね。
>一旦fcloseしてから変えないとまずいのでは?
試しに回避処理を試しましたが変わりませんでした。
下記に変更したテストプログラムを載せます。
CString fname = _T(C:\\test.txt); //
CString fname2 = _T(C:\\test.txt); //
CString dpath = _T(C:\\);
CString dname_l1 = _T(test1.txt); //
CString dname_l2 = _T(test2.txt); //
CFile file;
unsigned long fsize = 11;
file.Open(fname2, CFile::modeCreate|CFile::modeWrite);
if(file.m_hFile!=CFile::hFileNull){
fname = dpath + dname_l1;
fsize = _byteswap_ulong(0xFFFFFFF0); //
file.Write(&fsize, sizeof(fsize));
fname = dpath + dname_l2;
fsize = _byteswap_ulong(0xFFFFFFF0); //
file.Write(&fsize, sizeof(fsize));
file.Close();
}
2003ではないのですが・・・
VC2005,2008
MFC共有、スタティック切り替え
マルチバイト文字、ユニコード文字
以上、組み合わせ8パターンで試したけど、再現しませんでした
ryoさん情報ありがとうございます。
自分の環境だけで出ている現象なのでしょうか・・・
もう少し調べてみます。
調べ方などアドバイスがありましたら助言をよろしくお願いします。
>if(file.m_hFile!=CFile::hFileNull){
> fname = dpath + dname_l1;
> fsize = _byteswap_ulong(0xFFFFFFF0); //
> file.Write(&fsize, sizeof(fsize));
ここに
> file.Close();
> fname = dpath + dname_l2;
> file.Open(fname2, CFile::modeCreate|CFile::modeWrite);
> fsize = _byteswap_ulong(0xFFFFFFF0); //
> file.Write(&fsize, sizeof(fsize));
> file.Close();
>}
この方法だと、
>if(file.m_hFile!=CFile::hFileNull){
このif文が生きてこないですが........
二つ別々に入れるかですね。
ITOさんレスありがとうございます。
>このif文が生きてこないですが........
テストプログラムは現象だしをするためのプログラムですので
プログラム自体の有効性などは考慮していません。
無駄な処理でも現象を出す為には必要な処理となっています。
ITOさんのプログラムと私のとは微妙にコードが変わっているようです。
またryoさんの情報ではVCの2005・2008では現象が出ないようです。
私の方でも2005での確認が出来、現象が発生しませんでした。
10:45:37に載せたコードを2003の環境で
09:41:03に載せた手順で確認して頂けると
再現できると思われます。
2003の環境で現象を確認出来た方がいたら書き込みをお願いします。
逃げとしては2005に乗り換えて対応出来そうですがもう少し調べてみます。
VS2003 SP1で再現しました。
時間がないため、原因はまだ調べていません。
isshiさん確認ありがとうございます。
何かわかりましたらレスをお願いします。
Release版の混合モードで追ってみました。
fname = dpath + dname_l1; のアセンブリコード。
00401F32 lea edx,[esp+10h]
00401F36 push edx
00401F37 lea eax,[esp+0Ch]
00401F3B push eax
00401F3C lea ecx,[esp+1Ch]
00401F40 push ecx
00401F41 call ATL::operator+ (401D30h)
00401F46 add esp,0Ch
00401F49 push eax
00401F4A lea ecx,[esp+8]
00401F4E mov byte ptr [esp+34h],5
00401F53 call ATL::CSimpleStringT<char,0>::operator= (401B80h)
00401F58 mov eax,dword ptr [esp+14h]
00401F5C add eax,0FFFFFFF0h
00401F5F mov byte ptr [esp+30h],4
00401F64 lea edx,[eax+0Ch]
00401F67 or ecx,0FFFFFFFFh
00401F6A lock xadd dword ptr [edx],ecx
00401F6E dec ecx
00401F6F test ecx,ecx
00401F71 jg CTestDlg3Dlg::OnBnClickedButton1+0EBh (401F7Bh)
00401F73 mov ecx,dword ptr [eax]
00401F75 mov edx,dword ptr [ecx]
00401F77 push eax
00401F78 call dword ptr [edx+4]
00401F7B push esi
fname = dpath + dname_l2; のアセンブリコード。
00401F97 lea ecx,[esp+10h]
00401F9B push ecx
00401F9C lea edx,[esp+10h]
00401FA0 push edx
00401FA1 lea eax,[esp+20h]
00401FA5 push eax
00401FA6 call ATL::operator+ (401D30h)
00401FAB add esp,0Ch
00401FAE push eax
00401FAF lea ecx,[esp+0Ch]
00401FB3 mov byte ptr [esp+38h],6
00401FB8 call ATL::CSimpleStringT<char,0>::operator= (401B80h)
00401FBD mov eax,dword ptr [esp+18h]
00401FC1 add eax,esi // ここがおかしい。add eax,0FFFFFFF0h の間違いでは?
00401FC3 mov byte ptr [esp+34h],4
00401FC8 lea ecx,[eax+0Ch]
00401FCB or edx,0FFFFFFFFh
00401FCE lock xadd dword ptr [ecx],edx // ここで[ecx]がアクセス違反のため落
ちる。
00401FD2 dec edx
00401FD3 test edx,edx
00401FD5 jg CTestDlg3Dlg::OnBnClickedButton1+14Fh (401FDFh)
00401FD7 mov ecx,dword ptr [eax]
00401FD9 mov edx,dword ptr [ecx]
00401FDB push eax
00401FDC call dword ptr [edx+4]
コンパイラのバグのような気がします。