2

编辑#1:

用 wstring 的向量替换了 wchar_t 指针的向量。

我仍然遇到缓冲区溢出,但现在程序中崩溃的地方的数量已经大大减少了。

编辑#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, 一月, 二月, ..., 年>

关系是一对多的,因为一名员工拥有每年的月薪数据,如下所示:

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

一旦用户从组合框中选择了一个主键,他就可以通过在第一个编辑控件中键入它来更改有关月薪的数据,并且他必须在第二个编辑控件中键入年份。

输入的数据保存在一个声明如下的向量中:

   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;

然后用户必须输入年份,按下第二个按钮后,它的存储方式如下:

      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::wstringGetDlgItemText您一起使用,可以执行以下操作:

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 回答
1

崩溃的原因:你定义vector<wchar_t*>,用 和 填充你的向量,ee.assign( 13, L”-1” );wchar_t *temp = new wchar_t[50];删除delete[]。都错了。

delete[]运算符释放堆上分配的内存 ee.assign( 13, L”-1” );传递编译器分配的对象。那是错的。这些不在堆上,您不应该释放该内存,但是当您调用delete[].

您可以将向量定义为vector<std::wstring>然后将其用作

std::vector<std::wstring> v;
v.assign(10,L"xyz");
std::wstring s = L"abc";
v.push_back(s);
... etc.
v.clear(); // call destructor for every std::wstring in the vector

在您的按钮处理程序中:

wchar_t temp[50];
GetDlgItemTxt( ... , temp, ... );
v[i] = temp; // creates a wstring object and copies temp in there

您可以像以前一样定义向量并使用 new 和 delete,但您需要一个很好的理由。您负责为向量中的对象分配的内存。您不能混合分配在堆上、堆栈上或静态分配的指针(例如字符串字面量 L"-1")。

vector<wchar_t*> v;
v.assign(10, 0); // fill in with null pointers
wchar_t *ptr = new wchar_t[10];
... fill in ptr memory with data
v.push_back(ptr);
... etc.
// Now you need to free memory you allocated manually - You do not do that
// in case of std::vector<std::wstring>
for (vector<wchar_t*>::iterator it = v.begin(); it != v.end(); ++it)
    delete[] *it;

v.clear(); // clear function calls destructor for every object in the vector.
// There is no destructor for a pointer, hence the difference between
// deallocating vector<wstring> and vector<wchar_t*>
于 2013-09-09T01:58:27.770 回答