matrix new and delete / memory leak

Aug 3, 2010 at 5:29am
Hi,

There is a memory leak problem in my code, and I could not find where it is. The only place I use new/delete commands is for matrix. I am using the following way to create a matrix and free the memory when I am finished with it
-----------------------------------------
allocation:
double** Mat = new double* [row];
Mat[0] = new double [row * col];
for (int i = 1; i < row; ++i)
Mat[i] = Mat[i-1] + col;

deallocation:
delete [] Mat[0];
delete [] Mat;
-----------------------------------------
I think this way should free all the memory allocated by new and should not cause memory leak. Am I correct?

If I am right about this, then where else could memory leak happens? Memory issue is really a headache...

Thanks in advance!


Aug 3, 2010 at 10:19am
Here, have a look at this:
http://cplusplus.com/forum/articles/17108/
Aug 4, 2010 at 1:45am
Hi,

Thanks for the link. It is an interesting post, probably a more efficient way to implement multi-dim arrays, but does not solve my question.

I like the way to construct matrix in my first post. One nice feature of this way is that we do not need to pass other parameters at deallocation, except the double pointer. most other alternatives need a dimension parameter.

The thing I am not 100% sure whether the deallocation indeed frees all the memory is that, since we first delete[] Mat[0], the memory to store the actual data in the matrix is freed first. Thus after the first deletion, Mat[0], Mat[1],..., Mat[row-1] are probably null pointers (?), so when we delete[] Mat, do we free all the memory to hold these row pointers? I am thinking if these memory is not freed thoroughly, it may be the source of memory leak in my code.

Thanks.
Aug 4, 2010 at 1:48am
When you have an array of pointers to heap memory, you first have to release the memory that each pointer points to, then you can delete the array of pointers.
Aug 4, 2010 at 2:42am
according to this description, this deallocation should free all the memory. then I need to check where else could memory leak happens...

Thanks.
Aug 4, 2010 at 6:08am
closed account (oz10RXSz)
And how do you know there is a memory leak?
In most cases of allocation of small objects, delete does not return the freed memory to the OS. It just marks the region to be reused when the next call to new happens. That is why many programs with manual allocation behave like they had leaks, despite the fact they don't have any. If you are very unlucky, your program can consume several times more memory from the OS than is really needed. Long running applications that do heavy caching of small objects often suffer from this: e.g. Firefox.
Last edited on Aug 4, 2010 at 6:09am
Aug 4, 2010 at 8:51pm
My code is doing simulation, and I observe that the memory usage goes up when I have more replications. and when I set replication to be very large, my code will crash with a message saying "This application has requested the Runtime to terminate it in an unusual way", and the memory usage is indeed at the limit of my computer. So I think there must be a memory leak in the code. If there is no memory leak, while the memory usage can go up, it should not crash, right?
Aug 4, 2010 at 9:32pm
One thing I did not mention is the way I use the matrix. I do not write a matrix class, instead, I first construct the matrix (double pointer) in the main function, then I pass the matrix (double pointer) to a sub-function to do some work, then at the end of the main function, I delete the matrix by the deallocation procedure.

I was thinking when I pass the matrix to the sub-function, I essentially create a copy of the matrix, so maybe I need to delete the copy inside the sub-function, but this is not right when I tried it out. so I guess it should not be a memory leak here.
Aug 5, 2010 at 9:54am
The way you assign memory for the Mat arrays is kindof strange, maybe your problem is in there..

Also, In the article R0mai posted;
1
2
3
4
5
6
7
8
9
10
11
12
// let's say we want to dynamically make int[Y][X]:
int** superevil = new int*[Y];
for(int i = 0; i < Y; ++i)
  superevil[i] = new int[X];

// now we can do this:
superevil[2][3] = 1;

// but cleanup is just as ugly as allocation:
for(int i = 0; i < Y; ++i)
  delete[] superevil[i];
delete[] superevil;


You should probably just read the article and find a better solution instead of using int** Mat
Last edited on Aug 5, 2010 at 9:54am
Aug 6, 2010 at 12:46pm
closed account (oz10RXSz)
The problem must be somewhere else. Try to use valgrind or electric fence - these tools will help you find the source of the leak.

@skillness: your way of allocation is slooooow - exactly how you should not do it - much worse than that of majia1. Each call to new is about 80-200 CPU cycles for the best allocators available. If you program this way, any beginner Java coder would rewrite your code literally in Java, and then create another "Java faster than C++" post on his blog.
Last edited on Aug 6, 2010 at 12:51pm
Aug 6, 2010 at 2:11pm
Cool story bro,

If you would have read the article R0mai posted (instead of the article "Java faster than C++"), you woudlve known it is bad, and i think thats the reason the variable is called superevil
You should probably just read the article and find a better solution instead of using int** Mat
Last edited on Aug 6, 2010 at 2:12pm
Aug 6, 2010 at 4:09pm
closed account (oz10RXSz)
The article suggests using nested STL vectors which is just as slow - each vector needs to allocate and deallocate space. The approach of allocating one contiguous memory chunk and storing just pointers inside is much wiser, at least from the performance point of view. In languages with automatic allocation from contiguous memory chunk, you can new many times and it will be fast and will have good memory locality, but not in C++ - in C++ you need to plan your allocations very carefully.
Last edited on Aug 6, 2010 at 4:12pm
Aug 6, 2010 at 6:53pm
You mean you didnt read the second post?
Aug 8, 2010 at 4:14am
I believe the second post provides better way to handle multi-dim arrays. However, I have finished all my code using the way in the first post, so it is not easy to change to an alternative way. While people may say that way is not as pretty, it works and has its own advantages.

One remaining memory problem is very weird, I provide an concrete example under topic with the name "memory leak detect using _CrtDumpMemoryLeaks" ( http://www.cplusplus.com/forum/general/26994/ ), but I think it is quick relevant and re-post here.

I made up a concrete example to show the problem. here is my code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>

#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#ifdef _DEBUG
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#endif

using namespace std;

int main( )   
{
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
int Y = 1;
int X = 2;
int** superevil = new int*[Y];
for(int i = 0; i < Y; ++i)
	superevil[i] = new int[X];

superevil[0][2] = 1;

/*for(int i = 0; i < Y; ++i)
  delete[] superevil[i];
delete[] superevil;*/

 _CrtDumpMemoryLeaks();
return 0;
}


as you can see, I comment out the delete command and the memory allocated by new is not freed, so memory leak is detected with the a nice report with location information:

Detected memory leaks!
Dumping objects ->
c:\...\visual studio 2008\projects\memorytest\memorytest\memorytest.cpp(41) : {122} normal block at 0x00336658, 12 bytes long.
 Data: <            > CD CD CD CD CD CD CD CD 01 00 00 00 
c:\...\visual studio 2008\projects\memorytest\memorytest\memorytest.cpp(39) : {121} normal block at 0x00336618, 4 bytes long.
 Data: <Xf3 > 58 66 33 00 
Object dump complete.


Then I uncomment the delete statements, while I expect no memory leak, I get the report without location information:

Detected memory leaks!
Dumping objects ->
{120} normal block at 0x003365D8, 4 bytes long.
 Data: <    > 00 00 00 00 
Object dump complete.


Can anyone tell me is there indeed still a memory leak? if so, where is it? why no location information is reported?

Thanks.
Aug 8, 2010 at 4:39am
Mmmm... This here:

1
2
for(int i = 0; i < Y; ++i)
    superevil[i] = new int[X];

allocates 12 bytes, 4 for the int pointer (Y==1) and 8 for the two ints (X==2). And the error message for these 12 bytes disappears when you uncomment the delete statements. So, this is not the problem.

However, here:

superevil[0][2] = 1;

you have heap corruption. [0][2] is not a valid set of indices for your array. Maybe that's why you get that 4 byte error. Try commenting it out, or making it superevil[0][1] = 1; or superevil[0][0] = 1; and see what happens.
Last edited on Aug 8, 2010 at 4:40am
Aug 9, 2010 at 8:30pm
sorry I made a stupid mistake... now after fix this out of range problem, the previous code has no memory leak. but I identify the true problem--

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <vector>

#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#ifdef _DEBUG
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#endif

using namespace std;
int main( )   
{
	_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

   int** dd;
   int row=2;
   int col=3;
   
	dd = new int*[row];
	for(int i = 0; i < row; ++i)
	  dd[i] = new int[col];

   dd[0][2] = 3;
   cout<<"dd[0][2]= "<<dd[0][2]<<endl;
   
   vector<int**> v;
   v.push_back(dd);
   cout<<"v[0][0][2]= "<<v[0][0][2]<<endl;
   // note: I only push one element into v, so v.size() = 1

   for(int i = 0; i < row; ++i)
	  delete[] v[0][i];
   delete[] v[0];

   //v.~vector();

   _CrtDumpMemoryLeaks();
   return 0;
}


with the output:

Detected memory leaks!
Dumping objects ->
{144} normal block at 0x00336798, 4 bytes long.
 Data: <(f3 > 28 66 33 00 
Object dump complete.


Then I un-comment the line to call the destructor v.~vector(), and the memory leaks disappears. However, I think we do not need to call the vector destructor explicitly, since it will be called automatically when the code exit. so I am confused why there is a memory leak in the code without explict call of the vector destructor.

Aug 9, 2010 at 10:50pm
Try this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//...

int main( )   
{
    _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

    {
        //rest of the code here
        //...
    }

   _CrtDumpMemoryLeaks();
   return 0;
}

I don't think you have a memory leak. It just says you do because you call _CrtDumpMemoryLeaks(); before the vector destructor is called.
Aug 10, 2010 at 3:31am
ooh, I see. you are right. Thanks!
Aug 10, 2010 at 7:04pm
Line no 21 has problem,its writing beyond boundry error.it must be [0][1] instead of [0][2].
Topic archived. No new replies allowed.