views:

330

answers:

11

Turns out many innocently looking things are undefined behavior in C++. For example, once a non-null pointer has been delete'd even printing out that pointer value is undefined behavior.

Now memory leaks are definitely bad. But what class situation are they - defined, undefined or what other class of behavior?

A: 

defined, since a memory leak is you forgetting to clean up after yourself.

of course, a memory leak can probably cause undefined behaviour later.

Oren Mazor
It what why can a memory leak cause undefined behavior!
Martin York
What undefined behavior will a memory leak cause, other than eventually running out of memory. Dereferencing a pointer that is already freed will cause undefined behavior (like a segfault), but a memory leak is not immediately dangerous.
Tarydon
A memory leak CANNOT cause undefined behavior. For instance, in C too many memory leaks may eventually result in a `malloc` call returning `NULL`. But that is a defined behavior of `malloc`.
Stephen C
thats what I meant. the act of memory leaking is absolutely defined. running out of memory, for example, is not.
Oren Mazor
+6  A: 

Memory leaks are definitely defined in C/C++.

If I do:

int *a = new int[10];

followed by

a = new int[10]; 

I'm definitely leaking memory as there is no way to access the 1st allocated array and this memory is not automatically freed as GC is not supported.

But the consequences of this leak are unpredictable and will vary from application to application and from machine to machine for a same given application. Say an application that crashes out due to leaking on one machine might work just fine on another machine with more RAM. Also for a given application on a given machine the crash due to leak can appear at different times during the run.

gameover
An application is not going to crash with the code you have given above. It will eventually run out of memory, though.
Tarydon
Unknown and arbitrary consequences sound like the very definition of Undefined Behavior.
joshperry
@Joeshperry: Undefined Behavior: is a very specific term defined in the standard. It means the standard specifically does not specify the meaning of what will happen so that the implementation has enough flexibility to perform optimizations and generate appropriate optimal code. Thus arbitrary consequences is not related to undefined behavior (as defined by the standard).
Martin York
-1, there is nothing unpredictable about memory leaks.
avakar
@avakar: gameover is sort of on to something, though. Leaking memory is not undefined behavior, and running out of memory is also not undefined behavior. But *in practice* OSes frequently cause the C++ implementation to violate the standard if they run out of memory. For example they might over-commit memory, or the OS might inexplicably grind to a halt or fail internally as a consequence of application-level memory use. That's nothing to do with leaks in particular, though, just using all the memory.
Steve Jessop
Tarydon: In extreme situations the Linux kernel can kill a process that's just using too much memory and not doing anything else wrong. http://linux-mm.org/OOM_Killer It doesn't crash exactly; the system shoots it down.
Jason Orendorff
Steve Jessop, you are completely correct, but I don't see your point. The fact that Linux tends to kill processes for using too much memory has little to do with memory leaks.
avakar
The consequence of a persistent memory leak is that you eventually run out of memory. The consequence of running out of memory in practice might be unpredictable behaviour, because OSes are sometimes flakey in that respect. Being shot down cleanly is close to the "good" end of the spectrum. If A causes B, I'm not sure whether that means B has anything to do with A or not, but my point is just that gameover's warning is worth knowing about. It may or may not strictly be an answer to the question posed.
Steve Jessop
Steve, sorry, I explained myself poorly: the leaked and properly managed memory are the same from the perspective of the Linux out-of-memory killer. If you keep piling up leaks, the result will be the same as if you keep enlarging a vector. Leaks are not the only possible cause of the process being terminated on Linux.
avakar
Yes, there are other ways to guarantee that you'll run out of memory eventually. A persistent memory leak is just the most obvious ;-)
Steve Jessop
Yes, so it's my point that it's not the leak that's making the execution "unpredictable" on Linux.
avakar
It is if the app would not otherwise use up all the memory. Likewise, if someone puts a 10M array on the stack, you could say that's not what causes them to run out of stack, because maybe their app would have run out of stack anyway. Since it's a purely hypothetical app, with no known properties other than a memory leak, it's really impossible to speculate what "the" cause is of anything it does. So I can't say you're wrong...
Steve Jessop
Well, you convinced me. You probably would have convinced me yesterday, if I were thinking clearly enough :)
avakar
+1  A: 

Expand that repertoire of behaviors so you can call it by its proper name: a bug.

Hans Passant
memory leaks can exist in a program for years without being identified as a bug.
fupsduck
So can many other bugs.
UncleBens
A: 

Undefined behavior means, what will happen has not been defined or is unknown. The behavior of memory leaks is definitly known in C/C++ to eat away at available memory. The resulting problems, however, can not always be defined and vary as described by gameover.

fupsduck
That is not what "Undefined Behavior" means. Please read a copy of the standard.
Martin York
is your point that more exactly "undefined behavior" means that the exact behavior which arises is not specified by the standard?
fupsduck
+2  A: 

Its definately defined behaviour.

Consider a case the server is running and keep allocating heap memory and no memory is released even if there's no use of it. Hence the end result would be that eventually server will run out of memory and definately crash will occur.

Ashish
but before that a poorly written driver may assume memory it allocated is avaliable, when the allocation failed, and forge ahead causing a blue screen of death. Meanwhile Microsoft prints out a helpful error message prompting you to replace the driver without any indication of a memory leak.
fupsduck
and by the way - no new driver is available!
fupsduck
+10  A: 

Memory leaks.

There is no undefined behavior. It is perfectly legal to leak memory.

Undefined behavior: is actions the standard specifically does not want to define and leaves upto the implementation so that it is flexible to perform certain types of optimizations without breaking the standard.

Memory management is well defined.
If you dynamically allocate memory and don't release it. Then the memory remains the property of the application to manage as it sees fit. The fact that you have lost all references to that portion of memory is neither here nor there.

Of course if you continue to leak then you will eventually run out of available memory and the application will start to throw bad_alloc exceptions. But that is another issue.

Martin York
The 2003 standard 3.7.3.2/4 says "The effect of using an invalidpointer value (including passing it to a deallocation function) is undefined.33)" depending on your definition of "using" (which may not mean just dereferencing), then it could be considered invalid to just inspect the value of an invalid pointer.
Evan Teran
@Evan: Agreed, that is what the standard says. But (the way I read it) in this context using means using the object that was pointed at by the pointer. It does not imply that using the pointer 'value' is undefined behavior. If you take your argument to a natural conclusion and apply it to the NULL pointer! The NULL pointer is technically an invalid pointer, yet as long as you do not de-reference the pointer using its 'value' is well defined.
Martin York
I agree with what you are saying (and lets face it, i've never seen a machine where printing an invalid pointer did anything negative)... but, the standard also has a ton of rules spelling out how the NULL pointer may be compared and converted. I think this is simply an area where they could have been far more specific (especially since there are tons of people in the "you can't even look at an invalid pointer portably" camp. Oh well.
Evan Teran
@Evan: Withdraw my objects. After reading the accepted answer to the other question refereed to in the question. I now see how it can be undefined behavior and am removing that part of my answer (completely embarrassed). I am leaving the comments as they provide usefull information for others.
Martin York
*"Of course if you continue to leak then you will eventually run out of available memory and the application will start to throw bad_alloc exceptions."* In my experience, what really happens is that the process gets bigger and bigger and bigger and the system slowly grinds to a halt. But, yeah.
Jason Orendorff
@Jason: Then you have a very limited experience.
Martin York
A: 

Straight forward answer: The standard doesn't define what happens when you leak memory, thus it is "undefined". It's implicitly undefined though, which is less interesting than the explicitly undefined things in the standard.

Terry Mahaffey
+2  A: 

The language specification says nothing about "memory leaks". From the language point of view, when you create an object in dynamic memory, you are doing just that: you are creating an anonymous object with unlimited lifetime/storage duration. "Unlimited" in this case means that the object can only end its lifetime/storage duration when you explicitly deallocate it, but otherwise it continues to live forever (as long as the program runs).

Now, we usually consider a dynamically allocated object become a "memory leak" at the point in program execution when all references (generic "references", like pointers) to that object are lost to the point of being unrecoverable. Note, that even to a human the notion of "all references being lost" is not very precisely defined. What if we have a reference to some part of the object, which can be theoretically "recalculated" to a reference to the entire object? Is it a memory leak or not? What if we have no references to the object whatsoever, but somehow we can calculate such a reference using some other information available to the program (like precise sequence of allocations)?

The language specification doesn't concern itself with issues like that. Whatever you consider an appearance of "memory leak" in your program, from the language point of view it is a non-event at all. From the language point of view a "leaked" dynamically allocated object just continues to live happily until the program ends. This is the only remaining point of concern: what happens when program ends and some dynamic memory is still allocated?

If I remember correctly, the language does not specify what happens to dynamic memory which is still allocated the moment of program termination. No attempts will be made to automatically destruct/deallocate the objects you created in dynamic memory. But there's no formal undefined behavior in cases like that.

AndreyT
+4  A: 

If you leak memory, execution proceeds as if nothing happens. This is defined behavior.

Down the track, you may find that a call to malloc fails due to there not being enough available memory. But this is a defined behavior of malloc, and the consequences are also well-defined: the malloc call returns NULL.

Now this may cause a program that doesn't check the result of malloc to fail with a segmentation violation. But that undefined behavior is (from the POV of the language specs) due to the program dereferencing an invalid pointer, not the earlier memory leak or the failed malloc call.

Stephen C
A: 

Deleting twice is undefined, and using after deleting. Usually bad things happen but not every time.

Charles Eli Cheese
+1  A: 

If the space shuttle must take off in two minutes, and I have a choice between putting it up with code that leaks memory and code that has undefined behavior, I'm putting in the code that leaks memory.

But most of us aren't usually in such a situation, and if we are, it's probably by a failure further up the line. Perhaps I'm wrong, but I'm reading this question as, "Which sin will get me into hell faster?"

Probably the undefined behavior, but in reality both.

JohnMcG