2

編集#1:

wchar_t ポインターのベクトルを wstring のベクトルに置き換えました。

それでもバッファ オーバーフローが発生しますが、プログラム内のクラッシュする場所の数が大幅に減少しました。

編集#1.1:

    /****************************************************/
    /*                                                  */
    /*  It was the string parser that caused buffer     */
    /*  overflow !                                      */
    /*                                                  */
    /****************************************************/

ベクトルの不適切な使用に違いありませんが、それは別の質問に残します。

助けようとしたすべての人に、私から +1 を差し上げます。

私はあなたの答えを試しましたが、それらはすべてうまくいきました。

私は初心者なので wstring を使うのが怖かったのですが、コミュニティの助けのおかげで新しいことを学ぶことができたと思います。

ありがとうございました。

ありがとうございました。

よろしく。

必要な情報:

ノート:

この質問をできるだけ短くするために、これは単純化された説明です。

詳細については、追加の質問をしてください。さらに情報を提供します。

2 つの編集コントロール、2 つのボタン、およびコンボ ボックスを備えたダイアログ ボックスがあります。

ダイアログの作成時に、WM_INIDIALOG でデータベースとの接続が確立されます。このデータベースには、従業員の月給に関するデータが年単位で保持されます。

次に、従業員の主キーがコンボ ボックスに読み込まれます。

テーブルは次のようになります。

Table_Employee < #primary_key, ...>

Table_Salary < #pk_salary, $primary_key, January, February, ..., Year>

次のように、1 人の従業員が毎年の月給に関するデータを持っているため、関係は 1 対多です。

| | 1月 | ... | 年 | 年 | #pk_salary| $primary_key| | | 1000.51 | ... | 2012年 | 100025558 | 48089989891 | | | 2000.51 | ... | 2013年 | 552025558 | 48089989891 | ...

ユーザーがコンボ ボックスから主キーを選択すると、最初の編集コントロールに入力して月給に関するデータを変更でき、2 番目の編集コントロールに年を入力する必要があります。

入力されたデータは、次のように宣言されたベクトルに保持されます。

   INT_PTR CALLBACK dlgProcedure(HWND hwnd, UINT Message, 
           WPARAM wParam, LPARAM lParam )
   {
   static vector<wchar_t*> ee; // vector for monthly salaries and a year

   // this vector holds data for all thes

      tatic vector< vector<wchar_t*> >  Pee;  years
  ...

      case WM_INITDIALOG:
    {
                    // 12 months + 1 year = vector of 13 to store data 

                    ee.assign( 13, LoadedValue );                                   
                    ...

ユーザーが最初のボタンを押すと、その月のデータが上記のベクトルに次のように保存されます。

      case IDC_BUTTON_MONTH:
            {

                // needed, since we have vector of wchar_t*

                wchar_t *temp = new wchar_t[50]; 

                GetDlgItemInt( ... , temp, ... );

            UINT i = // ordinal of the month taken from checkbox

            ee[ i ] = temp;

次に、ユーザーは年を入力する必要があり、2 番目のボタンを押すと、次のように保存されます。

      case IDC_BUTTON_YEAR:
      {

         wchar_t *temp = new wchar_t[50]; // needed, since we have vector of wchar_t*

         GetDlgItemInt( ... , temp, ... );

         ee[12] = temp;

         // This means that all the data is collected
         // so we can store this year’s data in the vector for years

         Pee.push_back(ee);

このように、ベクトル Pee はすべての年 (2012 年、2013 年、...) のデータを保持し、ベクトル ee は詳細 (特定の年の月給) を保持します。

問題:

コンボ ボックスでの選択を変更した後、新しいデータを保存するために、すべてのベクトルをクリアする必要があります。

これを行うと、エラーが発生し、プログラムがスナップします。ウィンドウを閉じようとしたときにもクラッシュが発生します。

ベクトルをクリアするコードのセクションをコメントアウトすると、プログラムは動作しますが、ベクトルが適切にクリアされないため、新しいデータを保存するために使用できません。

重要な情報:

プログラムを起動してコンボ ボックスの選択を変更すると、ダイアログ ボックスが表示され、2 つのデバッガーが表示され、次のメッセージが表示されます。

SomeProgramName.exe[3300] で未処理の例外が発生しました。

MS Visual Studio 2008 のデバッグで、[例外] をクリックし、すべてをチェックしました。プログラムをデバッグ モードで起動すると、ダイアログ ボックスに次のメッセージが表示されます。

これは、ヒープの破損が原因である可能性があります。これは、MyProgramName.exe または読み込まれた DLL のバグを示しています。

これは、MyProgramName.exe にフォーカスがあるときにユーザーが F12 キーを押したことが原因である可能性もあります。

出力ウィンドウには、より多くの診断情報が表示される場合があります。

上で述べたように、クリーンアップ コードをコメント アウトした後、エラーは発生しなくなりました。

だからこそ、私の問題があると確信しています。

問題のあるコード スニペット:

WM_CLOSE のハンドラ:

   case WM_CLOSE:
        {
            // cleanup 

            for( vector<wchar_t*>::size_type i = 0; i < ee.size(); i++)
                delete[] ee[i];

            ee.clear();

            for( vector< vector<wchar_t*> >::size_type i = 0; i < pee.size(); i++)
               for( vector<wchar_t*>::size_type j = 0; j < pee[i].size(); j++)
                  delete[] pee[i][j];

            pee.clear();

            DestroyWindow( hDlg );
        }
        return TRUE;

コンボ ボックスのハンドラ:

    case IDC_COMBO12:
        {
            if(HIWORD(wParam) == CBN_SELCHANGE )
            {
                // cleanup 

                for( vector<wchar_t*>::size_type i = 0; i < ee.size(); i++)
                   delete[] ee[i];

                ee.clear();

                for( vector< vector<wchar_t*> >::size_type i = 0; i < pee.size(); i++)
                    for( vector<wchar_t*>::size_type j = 0; j < pee[i].size(); j++)
                       delete[] pee[i][j];

                pee.clear();

                // assign neutral values to vectors

                ee.assign( 13, L”-1” );

                for( int i = 2012; i < currentYear; i++ )
                   Pee.push_back(ee);

                // other commands, like loading data from database and so on...

質問:

私はポインタ ( ) のベクトルを持っているので、メソッドを使用してベクトルを空にvector < wchar_t* >することはできないと思います。メモリ リークが発生するからです。clear()

そのため、私の意見では、最初にポインターを削除してから、clear()メソッドを使用する必要があります。vector of を使用するのはこれが初めてwchar_t*なので、ここで何が間違っているのかコミュニティに尋ねます。

ハンドラーでこれらのベクトルを正しくリセットするにはどうすればよいですか?

追加情報を求めてください。喜んで提供します。

4

2 に答える 2

5

ポインターのベクトルがあるので ( vector < wchar_t* > )

そこにあなたの問題があります。ポインターのベクトルを使用しないでください。のベクトルを使用しstd::wstringます。そうすれば、これについて心配する必要はありません。

編集:あなたstd::wstringと一緒に使うにGetDlgItemTextは:

std::vector<std::wstring> ee;
wchar_t wchScratch[1024]; // should be big enough for any string you've added
GetDlgItemText(hWnd, iID, wchScratch, sizeof(wchScratch) / sizeof(wchScratch[0]));
ee.push_back(wchScratch);

または、もっと複雑なものが必要な場合は、次のようにすることができます。

int iLength = GetWindowTextLength(GetDlgItem(hWnd, iID));
std::wstring strTemp;
strTemp.resize(iLength + 1);
strTemp.resize(GetDlgItemText(hWnd, iID, &strTemp[0], strTemp.size()));
ee.push_back(strTemp);

基本的に、コントロールから文字列を取得する方法は何も変わりません。格納方法を変更するだけです。

于 2013-09-09T01:55:35.477 に答える