当我尝试对STL向量进行清理时,会发生未处理的异常 [英] Unhandled exception occurs when I try to do cleanup for STL vectors

查看:46
本文介绍了当我尝试对STL向量进行清理时,会发生未处理的异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑#3:



似乎在使用wstring后,问题出现在缓冲区溢出中。



更改下面的代码后(48而不是50),一切似乎都运行良好:

  wchar_t  temp [ 50 ],目的地[ 50 ]; 

GetDlgItem(...,temp, 48 );

swprintf_s(目的地, 50 ,L %s,temp);





这是针对那些观察我的代码比C ++更多C的成员:



你是对的,因为我使用的是纯Win32 API,所有的例子都在C中。



使用它在C ++中,我需要知道MFC,我现在还不知道。



对于那些试图提供帮助的人,你得到的是+5。



我已经尝试了你的答案,但它们都有效,但最好的建议只是使用wstring。



因为我是初学者,所以我很害怕这样做,但多亏了社区的帮助,我想我已经学会了新的东西。



再次感谢大家。



我要求的最后一件事是,如果有人可以简要解释一下为什么以上代码,当数字48被50代替时,会产生缓冲区溢出?



再次感谢大家。



问候。



编辑#2:



替换了wchar_t的向量带有wstring矢量的指针,但仍然会发生崩溃。



不过,性能更好。在我发现问题后,我会再次更新我的问题。



感谢所有发布答案和评论的会员,我们非常感谢。



问候。



编辑#1:



编辑问题以纠正出现在代码中的TYPOS(感谢pwasser先生指出他们)。



必要信息:

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

注意:



这是一个简化的描述,以便尽可能缩短这个问题。



如需了解更多信息,请咨询其他问题,我将提供更多信息。



我有一个带有2个编辑控件,2个按钮的对话框和组合框。



在创建对话框时,在WM_INIDIALOG中,与数据库建立连接,该数据库保存有关员工月薪的数据。



然后员工的主键被加载到组合框中。



表格如下: br $>


 Table_Employee< #primary_key,...> 
Table_Salary< #pk_salary, $ primary_key ,1月,2月,...,年份>





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



 |一月| ...... |年| #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; // 月薪和一年的向量

static vector<矢量< wchar_t *> >撒尿; // 此向量包含所有年份的数据
...
< span class =code-keyword> case WM_INITDIALOG:
{
// 12个月+ 1年= 13个存储数据的向量

ee.assign( 13 ,LoadedValue);

...





用户按下第一个按钮后,月份的数据保存在上面像这样的矢量:



  case  IDC_BUTTON_MONTH:
{
wchar_t * temp = new wchar_t [ 50 ];因为我们有wchar_t *

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

UINT i = // 从复选框中取得的月份序数

ee [i] = temp;





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



  case  IDC_BUTTON_YEAR:
{
wchar_t * temp = new wchar_t [ 50 ];因为我们有wchar_t *

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

ee [ 12 ] = temp;

// 这意味着收集了所有数据

// 所以我们可以将今年的数据存储在向量中

Pee.push_back(ee);





这样,矢量Pee持有所有年份的数据(2012年,2013年, ...),矢量ee包含具体内容(某年的月薪)。



THE PROBEM:

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



在组合框中选择更改后,我必须清除所有向量,以便存储新数据。



当我这样做时,我收到错误,并且我的程序快照。当我试图关闭窗口时也会发生崩溃。



如果我注释掉清除向量的代码部分,我的程序可以工作,但后来我无法使用它存储新数据,因为矢量没有正确清除。



重要信息:


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



一旦我启动程序并在组合框中更改选择,弹出一个对话框,提供了2个调试器,并显示以下消息:

 SomeProgramName.exe [3300]中发生未处理的异常。





在Debug中,在MS Visual Studio 2008中,我点击了Exceptions,并检查了

所有内容。



在调试模式下启动程序后,出现以下消息的对话框:



这可能是由于堆损坏,这表示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 (向量< wchar_t *> :: size_type j = 0 ; j< pee [i] .size (); j ++)
delete [] pee [i] [j];

pee.clear();
DestroyWindow(hDlg);
}
返回 TRUE;





Handler对于组合框:



  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 (向量< wchar_t *> :: size_type j = 0 ; j< pee [i] .size (); j ++)
delete [] pee [i] [j];

pee.clear();

// 为向量分配中性值

ee.assign( 13 ,L - 1 );

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

// 其他命令,例如从数据库加载数据等等......





问题:

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



因为我有一个指针向量(向量< wchar_t *> ),我相信我不能只使用clear()方法清空向量,因为它会导致内存泄漏。



这就是为什么,在我看来,我必须首先删除指针,然后才使用clear()方法。



这是我第一次使用wchar_t *的向量,所以我问社区我是什么意思在这里做错了吗?



如何在我的处理程序中正确重置这些向量?



我使用MS Visual Studio C ++和纯WIN32。要求提供更多信息,我很乐意提供这些信息。

解决方案

primary_key ,1月,2月,...,年份>





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



 |一月| ...... |年| #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; // 月薪和一年的向量

static vector<矢量< wchar_t *> >撒尿; // 此向量包含所有年份的数据
...
< span class =code-keyword> case WM_INITDIALOG:
{
// 12个月+ 1年= 13个存储数据的向量

ee.assign( 13 ,LoadedValue);

...





用户按下第一个按钮后,月份的数据保存在上面像这样的矢量:



  case  IDC_BUTTON_MONTH:
{
wchar_t * temp = new wchar_t [ 50 ];因为我们有wchar_t *

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

UINT i = // 从复选框中取得的月份序数

ee [i] = temp;





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



  case  IDC_BUTTON_YEAR:
{
wchar_t * temp = new wchar_t [ 50 ];因为我们有wchar_t *

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

ee [ 12 ] = temp;

// 这意味着收集了所有数据

// 所以我们可以将今年的数据存储在向量中

Pee.push_back(ee);





这样,矢量Pee持有所有年份的数据(2012年,2013年, ...),矢量ee包含具体内容(某年的月薪)。



THE PROBEM:

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



在组合框中选择更改后,我必须清除所有向量,以便存储新数据。



当我这样做时,我收到错误,并且我的程序快照。当我试图关闭窗口时也会发生崩溃。



如果我注释掉清除向量的代码部分,我的程序可以工作,但后来我无法使用它存储新数据,因为矢量没有正确清除。



重要信息:


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



一旦我启动程序并在组合框中更改选择,弹出一个对话框,提供了2个调试器,并显示以下消息:

 SomeProgramName.exe [3300]中发生未处理的异常。





在Debug中,在MS Visual Studio 2008中,我点击了Exceptions,并检查了

所有内容。



在调试模式下启动程序后,出现以下消息的对话框:



这可能是由于堆损坏,这表示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 (向量< wchar_t *> :: size_type j = 0 ; j< pee [i] .size (); j ++)
delete [] pee [i] [j];

pee.clear();
DestroyWindow(hDlg);
}
返回 TRUE;





Handler对于组合框:



  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 (向量< wchar_t *> :: size_type j = 0 ; j< pee [i] .size (); j ++)
delete [] pee [i] [j];

pee.clear();

// 为向量分配中性值

ee.assign( 13 ,L - 1 );

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

// 其他命令,例如从数据库加载数据等等......





问题:

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



因为我有一个指针向量(向量< wchar_t *> ),我相信我不能只使用clear()方法清空向量,因为它会导致内存泄漏。



这就是为什么,在我看来,我必须首先删除指针,然后才使用clear()方法。



这是我第一次使用wchar_t *的向量,所以我问社区我是什么意思在这里做错了吗?



如何在我的处理程序中正确重置这些向量?



我使用MS Visual Studio C ++和纯WIN32。要求提供更多信息,我很乐意提供。


对我来说看起来像是一个双删除问题。由于您正在加载ee对象,然后将其添加到小便中,删除小便的内容也会对ee做一些事情。



我一直在做的事情之一删除指针时立即将其设置为NULL。我相信这会解决你的崩溃问题。换句话说:



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





...但是这无法解决您删除相同的问题对象两次。想想小便对象包含什么。



顺便说一句,我建议使用不同的变量名。你似乎迷恋于'temp'这个名字,同样ee / pee也没有描述性。


EDIT#3:

It seems that after using wstring the problem was in the buffer overflow.

After changing the code like below ( putting 48 instead of 50 ), everything seems to work fine:

wchar_t temp[50], destination[50];

GetDlgItem( ... , temp, 48 );

swprintf_s( destination, 50, L"%s", temp );



This is directed to those members who observed that my code is more C than C++:

You are right, it is so because I use pure Win32 API, and all examples are in C.

To use it in C++ I need to know MFC, which I don't at this moment.

For all those who tried to help, you get +5 from me.

I have tried your answers and they all worked, but the best advice is just to use wstring.

I was afraid to do that since I am a beginner, but thanks to the help of the community I think I have managed to learn something new.

Thank you all, again.

The last thing I ask for is if somebody can explain me briefly why the above code, when number 48 is substituted with 50, creates buffer overflow ?

Thank you all again.

Regards.

EDIT#2:

Replaced vectors of wchar_t pointers with vectors of wstring, but crash still occurs.

Still, performance is better. After I isolate the problem I will update my question again.

Thanks to all members who posted their answers and comments, they are highly appreciated.

Regards.

EDIT#1:

EDITED QUESTION TO CORRECT TYPOS THAT APPEARED IN CODE SNIPPETS ( thank you Mr. pwasser for pointing them out ).

NECESSARY INFORMATION:
-------------------------------------
NOTE:

This is a simplified description, in order to keep this question as short as possible.

For further information ask additional questions, and I will provide more information.

I have a dialog box with 2 edit controls, 2 buttons and combo box.

On dialog creation, in WM_INIDIALOG, a connection is established with a database, which holds data about monthly salary of employees on a year basis.

Then primary keys of the employees are loaded into combo box.

Tables look like this:

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



Relationship is one to many, since one employee has data about monthly salary for every year, like this:

|  January | ... | Year | #pk_salary| $primary_key|
|  1000.51 | ... | 2012 | 100025558 | 48089989891 |
|  2000.51 | ... | 2013 | 552025558 | 48089989891 |
...



Once a user selects a primary key from combo box , he is able to change the data about monthly salary by typing it in first edit control, and he must type in the year in the second edit control.

Entered data is held in a vectors declared like this:

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

	static vector< vector< wchar_t* > >  Pee; // this vector holds data for all the years
	...
	case WM_INITDIALOG:
		{
		    // 12 months + 1 year = vector of 13 to store data 

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



After user pushes the first button , data for the month is saved in the above vector like this:

case IDC_BUTTON_MONTH:
	{
	    wchar_t *temp = new wchar_t[50]; // needed, since we have vector of wchar_t*
 
            GetDlgItemInt( ... , temp, ... );

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

	    ee[ i ] = temp;



Then user must enter year, and after pushing the second button it is stored like this:

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);



This way, vector Pee holds data for all the years ( 2012, 2013, ... ), and vector ee holds the specifics ( monthly salary for a certain year ).

THE PROBEM:
------------------------------

After selection in the combo box changes, I must clear all vectors, in order for new data to be stored.

When I do that, I get the error, and my program snaps. Crash occurs also when I try to close the window.

If I comment out the section of the code that clears vectors, my program works, but then I can not use it to store new data, since vectors are not cleared properly.

IMPORTANT INFORMATIONS:

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

Once I start program and change selection in combo box,a dialog box pops up, with 2 debuggers offered, and this message:

An unhandled exception occurred in SomeProgramName.exe[3300].



In Debug, in MS Visual Studio 2008, I have clicked on Exceptions, and checked
everything.

After I start the program in Debug mode, I get the dialog box with following message:

This may be due to a corruption of the heap, which indicates a bug in MyProgramName.exe or any of the DLLs it has loaded.

This may also be due to the user pressing F12 while MyProgramName.exe has focus.

The output window may have more diagnostic information.

As I have said above, after I comment out the cleanup code, error no longer occurs.

That is why I am very sure that there lies my problem.



PROBLEMATIC CODE SNIPPETS:

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

Handler for 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;



Handler for combo box:

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...



THE QUESTION:
--------------------------

Since I have a vector of pointers ( vector < wchar_t* > ) , I believe that I can’t just use clear() method to empty the vector since it would cause memory leaks.

That is why, in my opinion, I must delete pointer first, and only then use clear() method.

This is my first time using vector of wchar_t*, so I ask the community what am I doing wrong here?

How should I correctly reset those vectors in my handlers ?

I use MS Visual Studio C++, and pure WIN32. Ask for additional information, I will gladly provide them.

解决方案

primary_key, January, February, ..., Year>



Relationship is one to many, since one employee has data about monthly salary for every year, like this:

|  January | ... | Year | #pk_salary|


primary_key| | 1000.51 | ... | 2012 | 100025558 | 48089989891 | | 2000.51 | ... | 2013 | 552025558 | 48089989891 | ...



Once a user selects a primary key from combo box , he is able to change the data about monthly salary by typing it in first edit control, and he must type in the year in the second edit control.

Entered data is held in a vectors declared like this:

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

	static vector< vector< wchar_t* > >  Pee; // this vector holds data for all the years
	...
	case WM_INITDIALOG:
		{
		    // 12 months + 1 year = vector of 13 to store data 

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



After user pushes the first button , data for the month is saved in the above vector like this:

case IDC_BUTTON_MONTH:
	{
	    wchar_t *temp = new wchar_t[50]; // needed, since we have vector of wchar_t*
 
            GetDlgItemInt( ... , temp, ... );

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

	    ee[ i ] = temp;



Then user must enter year, and after pushing the second button it is stored like this:

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);



This way, vector Pee holds data for all the years ( 2012, 2013, ... ), and vector ee holds the specifics ( monthly salary for a certain year ).

THE PROBEM:
------------------------------

After selection in the combo box changes, I must clear all vectors, in order for new data to be stored.

When I do that, I get the error, and my program snaps. Crash occurs also when I try to close the window.

If I comment out the section of the code that clears vectors, my program works, but then I can not use it to store new data, since vectors are not cleared properly.

IMPORTANT INFORMATIONS:

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

Once I start program and change selection in combo box,a dialog box pops up, with 2 debuggers offered, and this message:

An unhandled exception occurred in SomeProgramName.exe[3300].



In Debug, in MS Visual Studio 2008, I have clicked on Exceptions, and checked
everything.

After I start the program in Debug mode, I get the dialog box with following message:

This may be due to a corruption of the heap, which indicates a bug in MyProgramName.exe or any of the DLLs it has loaded.

This may also be due to the user pressing F12 while MyProgramName.exe has focus.

The output window may have more diagnostic information.

As I have said above, after I comment out the cleanup code, error no longer occurs.

That is why I am very sure that there lies my problem.



PROBLEMATIC CODE SNIPPETS:

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

Handler for 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;



Handler for combo box:

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...



THE QUESTION:
--------------------------

Since I have a vector of pointers ( vector < wchar_t* > ) , I believe that I can’t just use clear() method to empty the vector since it would cause memory leaks.

That is why, in my opinion, I must delete pointer first, and only then use clear() method.

This is my first time using vector of wchar_t*, so I ask the community what am I doing wrong here?

How should I correctly reset those vectors in my handlers ?

I use MS Visual Studio C++, and pure WIN32. Ask for additional information, I will gladly provide them.


Looks like a double delete problem to me. Since you are loading the ee object, then adding it to pee, deleting the contents of pee will do something with ee as well.

One of the things I always do when deleting a pointer is immediately set it to NULL. I believe this will fix your crash problem here. In other words:

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



... but this admittedly doesn't fix the problem that you are deleting the same objects twice. Think about what the pee object contains.

By the way, I'd suggest different variable names. You seem enamoured with the name 'temp' and likewise ee/pee are not that descriptive.


这篇关于当我尝试对STL向量进行清理时,会发生未处理的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆