• Create Account

Memory Leaks

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

11 replies to this topic

#1Vanz  Members

204
Like
0Likes
Like

Posted 12 February 2013 - 08:41 PM

I always strive to write my programs so they are Rock Solid, please share what techniques and/or programs you use to hunt down those nasty memory leaks. Some common ones I run into

int i, a[10];

for(i=0;i<15;i++)
a[i]=i;


One technique I use to track them down or errors in general is I write a for loop to a high number say 100,000 then I keep calling that function. If it has a memory leak it will usually crash or I examine Task Manager-> Performance and watch the Free Memory shrink.

Another one, that I think causes a crash:


BitBlt(hdc, -5, -5 , 100 , 100, hdcPic, 0, 0, SRCCOPY);


When using GDI, does blitting outside the screen resolution cause a memory leak?

Any other common ones you can think of? An example is always helpful... how do you find em?

Thanks for sharing...

Vanz

#2ProvenDantheman  Members

111
Like
0Likes
Like

Posted 12 February 2013 - 08:51 PM

Well, I always make sure my dynamic arrays are deleted before allocating more memory, and I also make sure I allocate enough memory before accessing it.

Don't do this:

int * i = new int[10];

somefunc(){

i = new int[11];

}

int * i = new int[10];

somefunc(){

delete[]i;

i = new int[11];

}

Do not do this:

int * i = new int[10];

somefunc{

int var = i[11];

}

Make sure you allocated enough memory in your dynamic array.

Also, make sure you only call delete once, or if there is a possible instance of you calling delete twice, set the variable to NULL when you delete it. Deleting a NULL pointer has no effect.

Edited by ProvenDantheman, 12 February 2013 - 08:54 PM.

#3Khatharr  Members

7667
Like
2Likes
Like

Posted 12 February 2013 - 09:32 PM

rhuala, on 12 Feb 2013 - 18:49, said:

int i, a[10];
for(i=0;i&lt;15;i++)
a[i]=i;

That's not a memory leak. That's a buffer overrun. You can avoid it by not using magic numbers:
const size_t ARRAY_LENGTH = 10; //or whatever
int ary[ARRAY_LENGTH];
for(int i=0; i &lt; ARRAY_LENGTH; ++i) {
ary[i] = i;
}

Quote
One technique I use to track them down or errors in general is I write a for loop to a high number say 100,000 then I keep calling that function. If it has a memory leak it will usually crash or I examine Task Manager-&gt; Performance and watch the Free Memory shrink.

No bueno. This will only catch leaks that always happen, and it's too hard to distinguish from normal allocation behavior if leaks are small. Use a utility like VLD instead, and use smart pointers and RAII to make leakage a non-issue.

Quote
Another one, that I think causes a crash:

BitBlt(hdc, -5, -5 , 100 , 100, hdcPic, 0, 0, SRCCOPY);
When using GDI, does blitting outside the screen resolution cause a memory leak?

No. It clips the blit according to the target context.

You're confused about what a memory leak is, or at least about what causes them.

This is a memory leak:
int main() {
int* derp = new int;
return 0;
}

This is a harmless one, but it's a leak because memory is allocated and not freed. You avoid memory leaks by strictly following proper memory management practices like RAII.

The examples you gave were concerning buffer overrun behavior. You avoid overruns by limiting buffer actions by always implementing bounds checking. Write loops in such a way that they are made aware of - and are unable to pass beyond - the end of the buffer, etc. Use the secure CRT functions rather than the original ones.

ProvenDantheman, on 12 Feb 2013 - 18:59, said:
Also, make sure you only call delete once, or if there is a possible instance of you calling delete twice, set the variable to NULL when you delete it. Deleting a NULL pointer has no effect.

Obscuring a bug is not the same as fixing a bug. Your program should always be aware of its allocations and react intelligently. NULL deletion has its uses but abusing it to avoid implementing allocation control is like taking aspirin instead of going to the hospital after cutting your arm off.

Edited by Khatharr, 12 February 2013 - 09:53 PM.

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

#4Servant of the Lord  Members

33494
Like
0Likes
Like

Posted 12 February 2013 - 10:09 PM

I avoid dynamic memory except where performance is really needed, preferring the priority of: local or member variables -> smart pointers -> manual dynamic memory
I use std::vectors even when I need a static size (I'll switch to C++11's std::array for static sizes soon - last I checked that wasn't implemented in my compiler, but that was quite a while ago).
Other than that, I also avoid funky pointer manipulation, and in general prefer references where suitable.

(The latter two helping with memory corruption rather than memory leaks - something that I dread trying to debug)

Edited by Servant of the Lord, 12 February 2013 - 10:10 PM.

It's perfectly fine to abbreviate my username to 'Servant' or 'SotL' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames -

#5Hodgman  Moderators

49394
Like
0Likes
Like

Posted 12 February 2013 - 10:15 PM

rhuala, on 12 Feb 2013 - 18:49, said:

int i, a[10];
for(i=0;i&lt;15;i++)
a[i]=i;

That's not a memory leak. That's a buffer overrun. You can avoid it by not using magic numbers:
const size_t ARRAY_LENGTH = 10; //or whatever
int ary[ARRAY_LENGTH];
for(int i=0; i < ARRAY_LENGTH; ++i) {
ary[i] = i;
}

QFT - the OP's examples are all about memory corruption, not memory leaks at all

Another technique that you can use for arrays (but not arrays that have been cast/decayed into pointers) is:
template <typename T, int N> uint ArraySize(T(&)[N]) { return N; }
...
for(int i=0; i < ArraySize(ary); ++i) {
ary[i] = i;
}

#6Polarist  Members

172
Like
1Likes
Like

Posted 12 February 2013 - 10:53 PM

It may be not as efficient, but I tend to use STL everywhere (until I need to optimize).  It's much easier to maintain/read.

const int NUM_THINGS = 10;

std::vector<int> myThings(NUM_THINGS);

for( const auto& thing : myThings ){
do_something_with(thing);
}

It also makes it quite difficult to accidentally overrun your buffer.

Edited by Polarist, 12 February 2013 - 10:54 PM.

#7Vanz  Members

204
Like
0Likes
Like

Posted 13 February 2013 - 01:16 AM

rhuala, on 12 Feb 2013 - 18:49, said:



int i, a[10];
for(i=0;i&lt;15;i++)
a[i]=i;

That's not a memory leak. That's a buffer overrun. You can avoid it by not using magic numbers:


const size_t ARRAY_LENGTH = 10; //or whatever
int ary[ARRAY_LENGTH];
for(int i=0; i < ARRAY_LENGTH; ++i) {
ary[i] = i;
}

QFT - the OP's examples are all about memory corruption, not memory leaks at all

Another technique that you can use for arrays (but not arrays that have been cast/decayed into pointers) is:


template <typename T, int N> uint ArraySize(T(&)[N]) { return N; }
...
for(int i=0; i < ArraySize(ary); ++i) {
ary[i] = i;
}

okay my bad, I apologize... whatever it's called it leads to crashes or flaky behavior, I guess my technique sucks... although I never do allocate an array with a number, it's always a #define or const

Edited by rhuala, 13 February 2013 - 01:19 AM.

#8nfactorial  Members

735
Like
0Likes
Like

Posted 13 February 2013 - 02:28 AM

I just replace operator new and delete (and malloc and free) with my own memory manager. You can then inject data blocks at the front and back of the allocated memory and place a defined data block there. You can detect buffer overruns by validating they are unchanged (the typical term for this is 'sentinels'). You can also detect memory leaks easily, most of that functionality is removed in release or master builds for performance reasons, and it can becoime a fairly large module in itself depending how much functionality you want but it's the best way to track downn these issues that can occur in all levels of C++ programming.

n!

Edited by nfactorial, 13 February 2013 - 02:28 AM.

#9Khatharr  Members

7667
Like
0Likes
Like

Posted 13 February 2013 - 02:48 AM

rhuala, on 12 Feb 2013 - 23:24, said:
okay my bad, I apologize... whatever it's called it leads to crashes or flaky behavior, I guess my technique sucks... although I never do allocate an array with a number, it's always a #define or const

Not yelling at you. Just clarifying the difference between the concepts.
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

#10Felix Ungman  Members

1545
Like
0Likes
Like

Posted 13 February 2013 - 03:37 AM

please share what techniques and/or programs you use to hunt down those nasty memory leaks.

During development I try to use good coding practices like RAII when appropriate and not separating allocation/deallocation responsibility.

Then when there's time for a release I do a profiling session using the Instruments app that comes with Xcode. It's very good for tracking memory allocation and leaks, but sometimes I also turn on memory scribble and guards to do even more thorough testing.

openwar  - the real-time tactical war-game platform

#11Bacterius  Members

13100
Like
2Likes
Like

Posted 13 February 2013 - 04:31 AM

I typically just run valgrind on my program, it catches basically everything. Sometimes it's helpful enough to tell me exactly what is leaking, though generally it's easy enough to deduce that from the size of the leaked resource. Though that's under Linux, and I'm not sure if opengl and other large libraries work together well with valgrind, but never had a problem so far.

I usually don't worry too much about memory leaks anyway. If your program is leaking memory, you may just have forgot something somewhere and that's easy to fix. If your design is so bad that it is otherwise incapable of correctly freeing its memory, you have big architectural problems. So usually, I just run valgrind from time to time, to pick up any accidental leaks I might have missed, and I'm good to go. That's in C, anyway. In C++ it's almost impossible to leak memory with the RAII model.

Edited by Bacterius, 13 February 2013 - 04:32 AM.

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

#12Polarist  Members

172
Like
0Likes
Like

Posted 13 February 2013 - 04:48 AM

I just replace operator new and delete (and malloc and free) with my own memory manager. You can then inject data blocks at the front and back of the allocated memory and place a defined data block there. You can detect buffer overruns by validating they are unchanged (the typical term for this is 'sentinels'). You can also detect memory leaks easily, most of that functionality is removed in release or master builds for performance reasons, and it can becoime a fairly large module in itself depending how much functionality you want but it's the best way to track downn these issues that can occur in all levels of C++ programming.

n!

I'm very interested in this approach, could you share any resources that you find particularly useful for implementing this approach?  It seems like a very elegant way to approach this issue, and would be much cleaner syntax than what I'm used to doing (i.e. shenanigans in constructors or a clunky factory approach).

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.