mcrblog

vcpp-ml

2002年07月

31

[vcpp 00058955] Re: コンボボックスに「文字変換」フラグを指定した場合の動きについて

島野です。

> とりあえずの回避方法としてはスタック変数を指定すれば落ちなくなるので、
> それで対応しようと思いますが、何故落ちるのかが分かりません。

とりあえず原因は、わかりました。
Dr.ワトソンで、コールスタックを吐き出したら、
AddString() 関数が呼び出している、CharUpperBuff() API あたりで、
コケているようです。
試しに、以下のようなテストコードを書いてみたら、やはり同じ場所で、
落ちました。(文字リテラルを渡すのがマズイようです)
# って、やっぱり M$ のバグっぽい気がするんですけど・・・(^^;;;

<テストプログラム>
-----------------------------------------------------------------------------
int SetData( LPCTSTR lpszData )
{
    try
    {
        TRACE2( "lpszData = [%s](0x%08X)\n", lpszData, lpszData );
        CharUpperBuff( (LPTSTR)lpszData, lstrlen(lpszData) );
        //             ^^^^^^^^^^^^^^^^ 読み取り専用メモリを書き換えている!?
        TRACE2( "lpszData = [%s](0x%08X)\n", lpszData, lpszData );
    }
    catch( ... )
    {
        TRACE0( "Abnormal termination.\n" );
    }
    return 0;
}

int test()
{
    TCHAR szData[]          = _T("aaa");
    static TCHAR s_szData[] = _T("bbb");
    CString strData         = _T("ccc");
    LPCTSTR p               = _T("ddd");
//  SetData( szData );    // 落ちない
//  SetData( s_szData );  // 落ちない
//  SetData( strData );   // 落ちない
//  SetData( p );         // 落ちる
//  SetData( _T("eee") ); // 落ちる

    return 0;
}

void CTestDlg::OnButton1() 
{
//  m_cbTest.AddString( _T("aaa") );        // 落ちる
//  m_cbTest.InsertString( 0, _T("aaa") );  // 落ちる
//  m_cbTest.SetWindowText( _T("aaa") );    // 落ちない
    test();                                 // 落ちる
}

-----------------------------------------------------------------------------

ということで、とりあえず原因は、わかったのですが、良い回避方法が思いつきません。
今のところ、
-----------------------------------------------------------------------------
1. 人海戦術で 文字リテラル _T("") を (CString)_T("") のように置換する
2. 「1.」をマクロで置換する。
3. SetData() のような関数を用意し、その中で CString に変換する。
-----------------------------------------------------------------------------
と言った方法を考えているのですが、他に何か良い案などありませんでしょうか?

--
31

[vcpp 00058953] コンボボックスに「文字変換」フラグを指定した場合の動きについて

島野です。お世話になります。

現在、NT4.0/VC++5.0 → Win2K/VC++6.0 の移行作業をしています。
(VC++7.0 が出ているご時世なんですけど・・・(^^;;;)
その中で、ひとつ良く分からない事象が出てきたので、
ご意見を伺いたいと思いメールいたしました。

VC++6.0(SP5) の、CComboBox::AddString() 関数についてですが、
UNICODE / Debug バージョンだと落ちる場合があるようです。

再現手順は、
-------------------------------------------------------------
1. MFC AppWizard (exe) で、ダイアログベースのプログラムを作成

2. コンボボックスのリソース(IDcb_Test)を配置

3. リソースのタイプに、大文字変換(CBS_UPPERCASE)を指定
   例)
   COMBOBOX  IDcb_Test,7,7,69,26,CBS_DROPDOWN | CBS_SORT | 
             CBS_UPPERCASE | WS_VSCROLL | WS_TABSTOP

4. CComboBox の変数として、m_cbTest を追加

5. ダイアログの OnInitDialog() で、コンボボックス(m_cbTest)に
   文字リテラルを追加しようとするとkernel32 で、アクセス違反が
   発生する。(ただし、定義に _UNICODE を追加した場合のみ発生)
   例)
   m_cbTest.AddString( _T("aaa") ) 

6. スタック変数を指定した場合は、問題ないらしい。
   例1)
   TCHAR szData[] = _T("aaa");
   m_cbTest.AddString( szData );
   例2)
   CString strData = _T("aaa");
   m_cbTest.AddString( strData );   
-------------------------------------------------------------
といった感じです。
大文字変換(CBS_UPPERCASE)、または、小文字変換(CBS_LOWERCASE)を
指定しなければ落ちません。
また、ANSI バージョン、もしくは、UNICODE / Release バージョンなら
「文字変換」を指定していていも落ちません。

予想では「文字変換」を指定すると「文字リテラル」を書き換えようとして
アクセス違反になっているのでは?と思うのですがヘルプにそのような記述
は見当たりません。
もし、書き換えるような仕様だとしたら、プロトタイプ宣言は、
int AddString( LPCTSTR lpszString ); でなく、
int AddString( LPTSTR lpszString ); になっていると思うのですが・・・。

とりあえずの回避方法としてはスタック変数を指定すれば落ちなくなるので、
それで対応しようと思いますが、何故落ちるのかが分かりません。

どなたか、原因等ご存知の方、いらっしゃいましたらご教授お願いします。
--
31

[vcpp 00058953] コンボボックスに「文字変換」フラグを指定した場合の動きについて

島野です。お世話になります。

現在、NT4.0/VC++5.0 → Win2K/VC++6.0 の移行作業をしています。
(VC++7.0 が出ているご時世なんですけど・・・(^^;;;)
その中で、ひとつ良く分からない事象が出てきたので、
ご意見を伺いたいと思いメールいたしました。

VC++6.0(SP5) の、CComboBox::AddString() 関数についてですが、
UNICODE / Debug バージョンだと落ちる場合があるようです。

再現手順は、
-------------------------------------------------------------
1. MFC AppWizard (exe) で、ダイアログベースのプログラムを作成

2. コンボボックスのリソース(IDcb_Test)を配置

3. リソースのタイプに、大文字変換(CBS_UPPERCASE)を指定
   例)
   COMBOBOX  IDcb_Test,7,7,69,26,CBS_DROPDOWN | CBS_SORT | 
             CBS_UPPERCASE | WS_VSCROLL | WS_TABSTOP

4. CComboBox の変数として、m_cbTest を追加

5. ダイアログの OnInitDialog() で、コンボボックス(m_cbTest)に
   文字リテラルを追加しようとするとkernel32 で、アクセス違反が
   発生する。(ただし、定義に _UNICODE を追加した場合のみ発生)
   例)
   m_cbTest.AddString( _T("aaa") ) 

6. スタック変数を指定した場合は、問題ないらしい。
   例1)
   TCHAR szData[] = _T("aaa");
   m_cbTest.AddString( szData );
   例2)
   CString strData = _T("aaa");
   m_cbTest.AddString( strData );   
-------------------------------------------------------------
といった感じです。
大文字変換(CBS_UPPERCASE)、または、小文字変換(CBS_LOWERCASE)を
指定しなければ落ちません。
また、ANSI バージョン、もしくは、UNICODE / Release バージョンなら
「文字変換」を指定していていも落ちません。

予想では「文字変換」を指定すると「文字リテラル」を書き換えようとして
アクセス違反になっているのでは?と思うのですがヘルプにそのような記述
は見当たりません。
もし、書き換えるような仕様だとしたら、プロトタイプ宣言は、
int AddString( LPCTSTR lpszString ); でなく、
int AddString( LPTSTR lpszString ); になっていると思うのですが・・・。

とりあえずの回避方法としてはスタック変数を指定すれば落ちなくなるので、
それで対応しようと思いますが、何故落ちるのかが分かりません。

どなたか、原因等ご存知の方、いらっしゃいましたらご教授お願いします。
--
31

[vcpp 00058952] Re: リソース(String Table)について

どうもありがとうございます
うちだでございます

> 神野です。

> という理由からでしょう。

ちゃんと理由があるんですね
理解しました
 
> 私は、リソースIDの16単位で
> STRINGTABLE DISCARDABLE
> BEGIN
> ...
> END
> にまとめる、としています。(そのまんま)

私もそうします
どうもありがとうございました
31

[vcpp 00058952] Re: リソース(String Table)について

どうもありがとうございます
うちだでございます

> 神野です。

> という理由からでしょう。

ちゃんと理由があるんですね
理解しました
 
> 私は、リソースIDの16単位で
> STRINGTABLE DISCARDABLE
> BEGIN
> ...
> END
> にまとめる、としています。(そのまんま)

私もそうします
どうもありがとうございました
記事検索
Amazon.co.jp
  • ライブドアブログ