[SOLVED] Problems with the heap

Started by
9 comments, last by Sanctux 16 years, 4 months ago
I'm leaking some memory because of some mistake in my code. Basically, I'm creating a vector of pointers to Polygons. Then, I let the user create as many Polygons as he/she wants and I add 'em to the vector. After that, I delete the temporary pointer to the Polygon and set it to NULL. Here's the code:

// ...excluded for clarity


void createPolygon(vector<Polygon*> &polygons)
{
	int userInput;
	string polyName;

	while (1)
	{
		cout << "What type of polygon would you like to create?\n"
			 << "0. Go back\n"
			 << "1. Triangle\n"
			 << "2. Rectangle\n";

		cin >> userInput;

		if (!userInput)
			break;

		switch (userInput)
		{
		case 1:
			{
				cout << "Please enter the name of your new triangle: ";
				cin >> polyName;

				polygons.push_back(new Triangle(polyName));
			}
			break;
		case 2:
			break;
		default:
			cout << "Invalid choice.\n";
			break;
		}

		cout << endl;
	}
}

void displayInstructions()
{
	cout << "Please select an option:\n"
		 << "0. Exit\n"
		 << "1. Create a polygon\n"
		 << "2. View your polygons\n"
		 << "3. Delete a polygon\n";
}

void displayPolygons(vector<Polygon*> &polygons)
{
	int temp = 0;
	string tempName;
	for (vector<Polygon*>::iterator iter = polygons.begin(); iter != polygons.end(); ++iter)
	{
		++temp;
		tempName = ((*iter)->GetName());

		cout << temp << ". " << tempName << endl;
	}
}

int main()
{
	vector<Polygon*> polygons;
	int userInput;

	while (1)
	{
		displayInstructions();
		cin >> userInput;

		if (!userInput)
			break;

		cout << endl;

		switch (userInput)
		{
		case 1:
			createPolygon(polygons);
			break;
		case 2:
			displayPolygons(polygons);
			break;
		case 3:
			break;
		default:
			cout << "Invalid choice.\n";
			break;
		}

		cout << endl;
	}

	for (vector<Polygon*>::iterator iter = polygons.begin(); iter != polygons.end(); ++iter)
	{
		delete *iter;
		*iter = NULL;
	}

	polygons.clear();

	_CrtDumpMemoryLeaks();
	system("PAUSE");
	return 0;
}


Sorry if it's a bit messy at the moment. I plan to separate the code into multiple files later. Thanks in advance! [Edited by - Sanctux on November 23, 2007 5:48:09 AM]
Jack
Advertisement
A few stylistic issues aside, your code appears to be correct - in looking over it briefly I didn't spot any memory leaks.

I'm not familiar with _CrtDumpMemoryLeaks(), but you might Google it and see what comes up - for example, this link looks like it might be somewhat relevant.
Thank you for your reply!

What are these stylistic issues you speak of? I would very much like to learn from those.

_CrtDumpMemoryLeaks() is the function that helps me identify any memory leaks. When I call it, it will automatically tell me if there are any memory leaks in the output window.

Right now it's telling me I'm leaking something worth 4 bytes...

Please help.


Thanks in advance.

[Edited by - Sanctux on November 23, 2007 12:04:04 AM]
Jack
Are you having trouble finding where you leaked?

If so, #define _CRTDBG_MAP_ALLOC at the top of your code, before you include any headers, then run your program again in the debugger. This will tell _CrtDumpMemoryLeaks() to pinpoint the source file and line number where it detected a mismatched allocation/deallocation.

@jyk, _CrtDumpMemoryLeaks() is part of the VC++ Debug CRT library, it's been around since VC 4, and helps you track memory errors in your code. "Debugging Applications" explains it quite well.
Thank you, scorpion007.

This is the output:
Quote:
Detected memory leaks!
Dumping objects ->
{144} normal block at 0x002E51B0, 4 bytes long.
Data: < > 00 00 00 00
Object dump complete.


I'm not sure, but if the {144} part means the line number, my file contains only 118 lines.
Jack
Quote:Original post by Sanctux
Thank you, scorpion007.

This is the output:
Quote:
Detected memory leaks!
Dumping objects ->
{144} normal block at 0x002E51B0, 4 bytes long.
Data: < > 00 00 00 00
Object dump complete.


I'm not sure, but if the {144} part means the line number, my file contains only 118 lines.


144 is the allocation id.
No, that's not the line number. Here's an example of what the output should show.

leak.cpp
// compile with cl /D_DEBUG /MDd leak.cpp#define _CRTDBG_MAP_ALLOC#include <stdio.h>#include <crtdbg.h>int main(){	malloc(40); // leak 1	malloc(10); // leak 2	_CrtDumpMemoryLeaks();	return 0;}


And if you run it through a debugger (CDB, Visual Studio) you should get something like:

Detected memory leaks!Dumping objects ->leak.cpp(11) : {73} normal block at 0x00355AA0, 10 bytes long. Data: <          > CD CD CD CD CD CD CD CD CD CDleak.cpp(10) : {72} normal block at 0x00355A38, 40 bytes long. Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CDObject dump complete.
Where do I put /D_DEBUG /MDd main.cpp?

The output doesn't include my file name or line number.

I'm using Visual C++ to debug.
Jack
In main(), you create a vector, and as you add polygons to it, it gets larger and larger.

Calling clear() on a vector doesn't free the memory for the vector, it just empties it out (Sort of like closing a swimming pool for the night doesn't mean they drain the pool, they just get all the people [contents] out), for performance reasons.

That means that the memory for the vector is still allocated when you call _CrtDumpMemoryLeaks(). _CrtDumpMemoryLeaks() just dumps all allocations that haven't been freed, meaning the vector allocation shows up.

The simplest way to do this is to put all of the code in main() into another function or block, and then call _CrtDumpMemoryLeaks() after that block. For example:
int RealMain(){	vector<Polygon*> polygons;	int userInput;	while (1)	{		displayInstructions();		cin >> userInput;		if (!userInput)			break;		cout << endl;		switch (userInput)		{		case 1:			createPolygon(polygons);			break;		case 2:			displayPolygons(polygons);			break;		case 3:			break;		default:			cout << "Invalid choice.\n";			break;		}		cout << endl;	}	for (vector<Polygon*>::iterator iter = polygons.begin(); iter != polygons.end(); ++iter)	{		delete *iter;		*iter = NULL;	}	polygons.clear();	return 0;}int main(){	int retVal = RealMain();	_CrtDumpMemoryLeaks();	system("PAUSE");	return retVal;}
Quote:Original post by Sanctux
Where do I put /D_DEBUG /MDd main.cpp?

The output doesn't include my file name or line number.

I'm using Visual C++ to debug.


You put it on the command line -- if you want to build my simple example.

Since you are using VC++, just build the Debug version, and it will automatically have those settings set. You don't need to do anything there.

Just make sure you have #define _CRTDBG_MAP_ALLOC at the very top of your code.

This topic is closed to new replies.

Advertisement