Have a look at the following code. In this code at the start of execution the memory usage is 1020K. but at the end of execution the memory usage is 1144K. can somebody help me identify the memory leak. If func() is called five times the memory usage goes to 1500K+. If we don’t use the list the memory usage does not increase.
void func();
int _tmain(int argc, _TCHAR* argv[])
{
func();
return 0;
}
void func()
{
list<char*> list1;
list<char*>::iterator iter;
char* val;
for(int i=0; i<100000; i++)
{
val = new char[20];
for(int j=0; j<20;j++)
{
val[j] = 'A';
}
val[19] = '\0';
list1.push_back(val);
}
iter = list1.begin();
for(int k=0; k<100000;k++, iter++)
{
delete[] *iter;
*iter = NULL;
}
val = NULL;
list1.clear();
list1.empty();
}
I see no memory leak here, but I do see a lot of very poor code.
I see some hints in your code that you’re running under Windows, and when I gaze in to my crystal ball I think I see you checking Task Manager to detect memory leaks. Using Task Manager to detect memory leaks is like using broadsword to do surgery. TM might be able to give you a hint that there might be a large memory leak present in the system, but it is too far removed from your program and too coarse to be definitive. Instead of using TM to determine that there are or are not memory leaks, you need to use a tool dedicated to that job. Visual Studio has such a tool built-in.
When I use these buil-in facilities in your code:
…I see:
There are two memory leaks reported for a total of 40 bytes, so there is no broad memory leak here. Moreover, these are probably false positives, reporting such things as static memory allocations by the CRT and should be ignored.
However, as I said I do see a lot of very poor code. This isn’t a cause of memory leaks here, but they easily could be in real code.
You use a lot of magic numbers. Such as with
for(int i=0; i<100000; i++), where instead you should be iterating the list (for( list<char*>::iterator it = list1.begin(); it != list1.end(); ++it)), or at least asking the list how many elements it has (for( size_t i = 0; i < list1.size(); ++i ))You are using dynamic allocation/deallocation. You should instead be using RAII in cases where you really do need dynamic allocation, but avoiding dynamic allocation altogether whenever possible. In your case, instead of having a
list<char*>, you should have alist<std::string>instead.You are using hand-written loops, in places where you could be using algorithms provided by the Standard Library. Code you never write is the most reliable code. Instead of the inner loop initializing a char array, just do
std::string s(20,'A'), and instead of the outer loop setting each list member, use something likecopyortransform.Edit Here’s a re-farctored version of your function that addresses some of these issues I mention above:
The call to
generate_nuses a C++11 lambda, but could easily be refactored to use a functor or something else entirely.