Is it possible to create memory leak in C++ without heap allocation, through very bad design ?
One example I had in mind, please correct me if it does not do what I think it does:
#include <iostream>
#include <string>
void WhatIsYourName()
{
std::string name;
std::cout << "What is your name? ";
getline (std::cin, name);
std::cout << "Hello, " << name << "!\n";
WhatIsYourName();
}
int main()
{
WhatIsYourName();
}
To me it looks like WhatIsYourName() is initializing a new std::string name on every call, but the function never really goes out of scope so the memory is never released.
Is that right ? Or is the compiler smart enough to see that the variable will not be used in the future, so it deletes it without the function going out of scope ?
What kind of other bad design would create a memory leak using only stack allocation ?
You have a recursive call that doesn't stop (there's no exit condition), so a new stack page is created for every function invocation, until of course the program crashes due to stack overflow. The compiler cannot optimize that away.
Regarding your last question, whether is possible to create a memory leak without heap allocation (and without this kind of infinite recursion), I believe it is not, the local variables are automatically released, that's why this type of storage duration is called automatic storage duration.
No it is not possible to create a memory leak with objects that have automatic storage duration (some people call this stack). When you have a variable with automatic storage duration it is cleaned up by the program automatically. Once the scope ends that it was declared in it gets destroyed and any resources it had are freed (as long as it was designed properly). In your example even though you never exit the scope due to infinite recursion it is not a memory leak. If the infinite recursion was removed and instead it ended at some condition then all the variables you declared would be cleaned up.
To get a memory leak you need to create a object with dynamic storage duration (what some people call heap) and never clean it up. When you have a object with dynamic storage duration the compiler does not clean it up for you. You need to make sure you clean it up yourself. It is this forgetting or leaving out of the clean up code that causes a memory leak.
The question is more interesting than you probably thought. There is no memory leak by definition, since memory leak can only be happening if a) a pointer to the allocated memory is lost (not the case here) or b) the pointer is never freed until program exits normally. The second is not the case either, since this program will never exit normally.
However, there is an interesting question of what actually happens to the string variable. Since the recursive call happens in the end of the function, from the glance it might seem that the code will be a candidate for tail-call optimization. However, if you check the assembly, it does not happen, because compiler needs to call string destructor after the return from the tail-call. I personally see this is a flaw in the optimization, since potentially compiler should be able to see that string variable is not used after the call and destruct it in advance.
I think you have misunderstood what a memory leak is in C and C++ worlds.
Given your condition "without heap allocation", it's not possible to leak memory.
A memory leak is typically associated with dynamic memory allocation(s) and then losing the ability to deallocate it.
For example:
// Memory leak
int x;
int *q = new int;
q = &x; // memory leak because the "allocated" q is lost.
With RAII and not using new + delete for memory management, it's easily avoidable in C++.
If the compiler has a bug, you could have a stack memory leak. For some obscure reason it "forgets" to call the destructor of a local variable. Check GCC bug 66139.
Related
I'm maintaining a legacy C++ application that seems to have a slow memory leak. I've managed to "fix" the memory leak by ensuring that the current configuration no longer throws any exceptions and I can also trigger the leak and scale it by configuring it to result in many exceptions.
All the memory that is allocated is done using alloca() rather than malloc(). The explanation I've been given for this is that it's because alloca() works like the java garbage collector and automatically frees the memory when it exits the context.
Due to the leak being so clearly bound to the exceptions being thrown I have the theory that alloca() is failing to free the memory when exceptions are thrown.
Is this at all plausible? It strikes me as a major defect in alloca() if true but when I google alloca() it seems to generally be a problem.
I'd appreciate the insight on any experts.
It is likely that the problem is due to a level of indirection.
The literal question is "does alloca return memory if an exception is thrown?". And the answer to that is; It returns only the memory that was directly allocated. No destructors are run, and any owning pointer inside the alloca-allocated memory is leaked.
In C++ you should not be using the C memory management routines. In modern C++ the smart pointers provide you with fine grained deterministic garbage collection.
Though the space allocated via alloca() is probably deallocated with exceptions (because it is usually done by increasing the size of the current stack frame). This is not part of the standard and thus I don't think you can make any guarantees.
BUT This also means that any appropriate destructors on the object are never going to be called. Which means that if the object does its own memory management this will not be cleaned up (because the destructor is not run to clean it up).
Though alloca() is probably very fast. I think the extra burden it adds for memory management is (in the general case) not worth it; though if you have a special need for extra speed it may be worth it.
Code the looks like this:
void func()
{
MyType* x = (MyType*)alloca(sizeof(MyType));
passXtoCFunctionThatDoesNotTakeOwnership(x);
}
Should be written like this:
void func()
{
std::unique_ptr<MyType> x = std::make_unique<MyType>();
passXtoCFunctionThatDoesNotTakeOwnership(x.get());
}
If you are using it to hold an array of objects.
void func()
{
MyType* x = (MyType*)alloca(sizeof(MyType) * arraySize);
// STUFF
x[0].stuff();
}
Then it is better to use a std::vector
void func()
{
std::vector<MyType> x;
x.reserve(arraySize); // or resize() if that is appropriate
// STUFF
x[0].stuff();
}
If you are using it for simple objects. Then you should probably just be declaring automatic variables:
void func()
{
MyType* x = (MyType*)alloca(sizeof(MyType));
x->myData = 5;
}
You should just be declaring a variable:
void func()
{
MyType x;
x.myData = 5;
}
From Linux man
....
Because the space allocated by alloca() is allocated within the stack
frame, that space is automatically freed if the function return is
jumped over by a call to longjmp(3) or siglongjmp(3).
....
The inlined code often consists of a single instruction adjusting the
stack pointer, and does not check for stack overflow. Thus, there is
no NULL error return.
.....
Bugs There is no error indication if the stack frame cannot be
extended. (However, after a failed allocation, the program is likely
to receive a SIGSEGV signal if it attempts to access the unallocated
space.) On many systems alloca() cannot be used inside the list of
arguments of a function call, because the stack space reserved by
alloca() would appear on the stack in the middle of the space for the
function arguments.
In this way, exception cannot cause memory leak for memory allocated by alloca in the stack frame. However, this, like any exception, can lead to heap memory leaks since destructors and memory freeing methods placed after alloca will be skipped.
The languages in question are C/C++.
My prof said to free memory on the heap when your done using it, because otherwise you can end up with memory that can't be accessed. The problem with this is you might end up with all your memory used up and you are unable to access any of it.
Why doesn't the same concept apply to the stack? I understand that you can always access the memory you used on the stack, but if you keep creating new variables, you will eventually run out of space right? So why can't you free variables on the stack to make room for new variables like you can on the heap?
I get that the compiler frees variables on the stack, but thats at the end of the scope of the variable right. Doesn't it also free a variable on the heap at the end of its scope? If not, why not?
Dynamically allocated objects ("heap objects" in colloquial language) are never variables. Thus, they can never go out of scope. They don't live inside any scope. The only way you can handle them is via a pointer that you get at the time of allocation.
(The pointer is usually assigned to a variable, but that doesn't help.)
To repeat: Variables have scope; objects don't. But many objects are variables.
And to answer the question: You can only free objects, not variables.
The end of the closed "}" braces is where the stack "frees" its memory. So if I have:
{
int a = 1;
int b = 2;
{
int c = 3; // c gets "freed" at this "}" - the stack shrinks
// and c is no longer on the stack.
}
} // a and b are "freed" from the stack at this last "}".
You can think of c as being "higher up" on the stack than "a" and "b", so c is getting popped off before them. Thus, every time you write a "}" symbol, you are effectively shrinking the stack and "freeing" data.
There are already nice answers but I think you might need some more clarification, so I'll try to make this a more detailed answer and also try to make it simple (if I manage to). If something isn't clear (which with me being not a native english speaker and having problems with formulating answers sometimes might be likely) just ask in the comments. Also gonna take the use the Variables vs Objects idea that Kerrek SB uses in his answer.
To make that clearer I consider Variables to be named Objects with an Object being something to store data within your program.
Variables on the stack got automatic storage duration they automatically get destroyed and reclaimed once their scope ends.
{
std::string first_words = "Hello World!";
// do some stuff here...
} // first_words goes out of scope and the memory gets reclaimed.
In this case first_words is a Variable (since it got its own name) which means it is also an Object.
Now what about the heap? Lets describe what you might consider being "something on the heap" as a Variable pointing to some memory location on the heap where an Object is located. Now these things got what's called dynamic storage duration.
{
std::string * dirty = nullptr
{
std::string * ohh = new std::string{"I don't like this"} // ohh is a std::string* and a Variable
// The actual std::string is only an unnamed
// Object on the heap.
// do something here
dirty = ohh; // dirty points to the same memory location as ohh does now.
} // ohh goes out of scope and gets destroyed since it is a Variable.
// The actual std::string Object on the heap doesn't get destroyed
std::cout << *dirty << std::endl; // Will work since the std::string on the heap that dirty points to
// is still there.
delete dirty; // now the object being pointed to gets destroyed and the memory reclaimed
dirty = nullptr; can still access dirty since it's still in its scope.
} // dirty goes out of scope and get destroyed.
As you can see objects don't adhere to scopes and you got to manually manage their memory. That's also a reason why "most" people prefer to use "wrappers" around it. See for example std::string which is a wrapper around a dynamic "String".
Now to clarify some of your questions:
Why can't we destroy objects on the stack?
Easy answer: Why would you want to?
Detailed answer: It would be destroued by you and then destroyed again once it leaves the scope which isn't allowed. Also you should generally only have variables in your scope that you actually need for your computation and how would you destroy it if you actually need that variable to finish your computation? But if you really were to only need a variable for a small time within a computation you could just make a new smaller scope with { } so your variable gets automatically destroyed once it isn't needed anymore.
Note: If you got a lot of variables that you only need for a small part of your computation it might be a hint that that part of the computation should be in its own function/scope.
From your comments: Yeah I get that, but thats at the end of the scope of the variable right. Doesn't it also free a variable on the heap at the end of its scope?
They don't. Objects on the heap got no scope, you can pass their address out of a function and it still persists. The pointer pointing to it can go out of scope and be destroyed but the Object on the heap still exists and you can't access it anymore (memory leak). That's also why it's called manual memory management and most people prefer wrappers around them so that it gets automatically destroyed when it isn't needed anymore. See std::string, std::vector as examples.
From your comments: Also how can you run out of memory on a computer? An int takes up like 4 bytes, most computers have billions of bytes of memory... (excluding embedded systems)?
Well, computer programs don't always just hold a few ints. Let me just answer with a little "fake" quote:
640K [of computer memory] ought to be enough for anybody.
But that isn't enough like we all should know. And how many memory is enough? I don't know but certainly not what we got now. There are many algorithms, problems and other stuff that need tons of memory. Just think about something like computer games. Could we make "bigger" games if we had more memory? Just think about it... You can always make something bigger with more resources so I don't think there's any limit where we can say it's enough.
So why can't you free variables on the stack to make room for new variables like you can on the heap?
All information that "stack allocator" knows is ESP which is pointer to the bottom of stack.
N: used
N-1: used
N-2: used
N-3: used <- **ESP**
N-4: free
N-5: free
N-6: free
...
That makes "stack allocation" very efficient - just decrease ESP by the size of allocation, plus it is locality/cache-friendly.
If you would allow arbitrary deallocations, of different sizes - that will turn your "stack" into "heap", with all associated additional overhead - ESP would not be enough, because you have to remember which space is deallocated and which is not:
N: used
N-1: free
N-2: free
N-3: used
N-4: free
N-5: used
N-6: free
...
Clearly - ESP is not more enough. And you also have to deal with fragmentation problems.
I get that the compiler frees variables on the stack, but thats at the end of the scope of the variable right. Doesn't it also free a variable on the heap at the end of its scope? If not, why not?
One of the reasons is that you don't always want that - sometimes you want to return allocated data to caller of your function, that data should outlive scope where it was created.
That said, if you really need scope-based lifetime management for "heap" allocated data (and most of time it is scope-based, indeed) - it is common practice in C++ to use wrappers around such data. One of examples is std::vector:
{
std::vector<int> x(1024); // internally allocates array of 1024 ints on heap
// use x
// ...
} // at the end of the scope destructor of x is called automatically,
// which does deallocation
Read about function calls - each call pushes data and function address on the stack. Function pops data from stack and eventually pushes its result.
In general, stack is managed by OS, and yes - it can be depleted. Just try doing something like this:
int main(int argc, char **argv)
{
int table[1000000000];
return 0;
}
That should end quickly enough.
Local variables on the stack don't actually get freed. The registers pointing at the current stack are just moved back up and the stack "forgets" about them. And yes, you can occupy so much stack space that it overflows and the program crashes.
Variables on the heap do get freed automatically - by the operating system, when the program exits. If you do
int x;
for(x=0; x<=99999999; x++) {
int* a = malloc(sizeof(int));
}
the value of a keeps getting overwritten and the place in the heap where a was stored is lost. This memory is NOT freed, because the program doesn't exit. This is called a "memory leak". Eventually, you will use up all the memory on the heap, and the program will crash.
The heap is managed by code: Deleting a heap allocation is done by calling the heap manager. The stack is managed by hardware. There is no manager to call.
Consider the following program:
int main() {
while(...) {
int* foobar = new int;
}
return 0;
}
When does foobar go out of scope?
I know when using new, attributes are allocated on the heap and need to be deleted manually with delete, in the code above, it is causing a memory leak. However, what about scope?
I thought it would go out of scope as soon as the while loop terminates, because you have no direct access to it anymore. For example, you cannot delete it after the loop has terminated.
Be careful here, foobar is local to the while loop, but the allocation on the heap has no scope and will only be destructed if you call delete on it.
The variable and the allocation are not linked in any way as far as the compiler is concerned. Indeed, the allocation happens at run time, so the compiler never even sees it.
foobar is a local variable that goes out of scope at the end of the block.
*foobar is a dynamically allocated object with manual lifetime. Since it doesn't have scoped lifetime, the question makes no sense -- it doesn't have a scope out of which it could go. Its lifetime is managed manually, and the object lives until you delete it.
Your question is dangerously burdened with prejudice and preconceptions. It is best to approach C++ with a clean mind and an open attitude. Only that way will you be able to appreciate the language's wonders to the fullest.
Here's the clean and open approach: Do think about 1) storage classes (automatic, static, dynamic), 2) object lifetime (scoped, permanent, manual), 3) object semantics (value (copies) vs reference (aliases)), 4) RAII and single-responsiblity classes. Purge your mind of a) stack/heap, b) pointers, c) new/delete, d) destructors/copy constructors/assignment operators.
That's a pretty awesome memory leak. You have a variable on the stack pointing to the memory allocated on the heap. You need to delete the memory on the heap before you lose the reference to it when the while loop scope ends. Alternately if you don't want to fuss with memory management always use smart pointers to own the raw memory on the heap and let it clean itself up.
#include <memory>
int main() {
while(...) {
std::unique_ptr<int> foobar = new int;
} // smart pointer foobar deletes the allocated int each iteration
return 0;
}
The pointer (foobar) will go out of scope right as the program gets to the closing brace of the while loop. So if the expression in the ... remains true, memory will be leaked every time the loop executes as you have lost a handle to the allocated object as of that closing brace.
Here foobar is an int pointer occupying memory in the stack. The int instance you are creating dynamically with new goes to heap. When foobar goes out of scope, you lose the reference to it, so you cannot delete the memory allocated in the heap.
The best solution would be:
while(--)
{
int foobar;
}//it goes out of scope here. deleted from stack automatically!!
If you still want to use the dynamic allocation then do this:
while(--)
{
int* foobar=new int;
//do your work here!
delete foobar; //This deletes the heap memory allocated!
foobar=NULL; //avoid dangling pointer! :)
}
foobar goes out of scope after each interation of the loop.
The memory you allocate and assign to foobar is being leaked, in that it is still allocated on the heap but no references to it are available in the program.
Since foobar is declared in the body of the loop, it goes out of scope at the end of every iteration of the loop. It is then redeclared, and new memory is allocated again and again until the loop ends. The actual object that foobar points to never goes out of scope. Scope doesn't apply to dynamically allocated(aka heap) objects, only to automatic(stack) objects.
Foobar the pointer is created on the stack, but the new int is created on the heap. In the case of the while loop, each time the code loops, foobar falls out scope. The newly created int persists on the heap. On each iteration a new int is created, and the pointer is reset, which means the pointer no longer can access any of the previous int(s) on the heap.
What seems to be lacking, in every one of the previous answers, and even in this one, is the heap falling out of scope. Maybe, I am getting the terminology incorrect, but I know that at some point the heap is reset, too. It may occur once the program no longer runs, or when the computer is turned off, but I know it occurs.
Let us look at this question from a different perspective. I have written any number of programs, which leak memory. Over all the years, I have owned my computer, I am positive, I have leaked over 2 gigabytes of memory. My computer only has 1 gig of memory. Therefore, if the heap NEVER falls out of scope, then my computer has some magical memory. Would one of you care to explain when exactly the heap falls out of scope?
Suppose I have a class named A:
Class A
{
...
}
And what's the difference between the following 2 approaches to instanciate an object:
void main(void)
{
A a; // 1
A *pa=new A(); // 2
}
As my current understanding (not sure about this yet):
Approach 1 allocate the object a on the stack frame of the main() method, and so this object cannot deleted because that deletion doesn't make sense (don't know why yet, could someone explain that?).
Approach 2 allocate the object a on the heap of the process and also a A* vairable pa on the stack frame of the main() method, so the object can be deleted and and the pa can be assigned null after the deletion.
Am I right? If my understanding is correct, could someone tell me why i cannot delete the a object from the stack in approach 1?
Many thanks...
Object a has automatic storage duration so it will be deleted automatically at the end of the scope in which it is defined. It doesn't make sense to attempt to delete it manually. Manually deletion is only required for objects with dynamic storage duration such as *pa which has been allocated using new.
The objects live time is limited to
the scope the variable is defined
in, once you leave the scope the
object will be cleaned up. In c++ a
scope is defined by any Block
between { an the corresponding }.
Here only the pointer is on the stack and not the object, so when
you leave the scope only the pointer
will be cleaned up, the object will
still be around somewhere.
To the part of deleting an object, delete not only calls the destructor of your object but also releases its memory, this would not work as the memory management of the stack is automated by the compiler, in contrast the heap is not automated and requires calls to new and delete to manage the live time of an object.
Any object created by a call to new has to be deleted once, forgetting to do this results in an memory leak as the objects memory will never be released.
Approach 1 declared a variable and created an object. In Approach 2, you created an instance and pointer to it.
EDIT : In approach 1, the object will go out of scope and will be automatically deleted. In approach 2, the pointer will be automatically deleted, but not what it is pointing to. That will be your job.
Imagine stack as void* stack = malloc(1.000.000);
Now, this memory block is managed internally by the compiler and the CPU.
It is a shared piece of memory. Every function can use it to store temporary objects there.
That's called automatic storage. You cannot delete parts of that memory because its purpose is
to be used again again. If you explicitly delete memory, that memory returns back to the system,
and you don't want that to happen in a shared memory.
In a way, automatic objects are also get deleted. When an object gets out of scope the compiler places
an invisible call to object's destructor and the memory is available again.
You cannot delete objects on the stack because it's implemented in memory exactly that way -- as a stack. As you create objects on the stack, they are added on top of each other. As the objects leave scope, they are destroyed from the top, in the opposite order they were created in (add to the top of the stack, and remove from the top of the stack). Trying to call delete on something in the stack would break that order. The analogy would be like trying to pull some paper out of the middle of a stack of papers.
The compiler controls how objects are created and removed on the stack. It can do this because it knows exactly how large each object on the stack is. Since the stack size is set at compile time, it means that allocating memory for things on the stack is extremely fast, much faster than allocating memory from the heap, which is controlled by the operating system.
Allocation does two things:
1) Allocates memory for the object
2) Calls the constructor on the allocated memory
Deletion does two things:
1) Calls the destructor on the object
2) Deallocates the memory used by the destructed object
When you allocate on the stack (A a;), you're telling the compiler "please make an object for me, by allocating memory, then call the constructor on that memory. And while you're at it, could you handle calling the destructor and freeing the memory, when it goes out of scope? Thanks!". Once the function (main) ends, the object goes out of scope, the destructor is called, and the memory is freed.
When you allocate on the heap (A* pa = new A();), you're telling the compiler "please make an object for me. I know what I'm doing, so don't bother calling the destructor or freeing the memory. I'll tell you when to do it, some other time". Once the function (main) ends, the object you allocated stays in scope, and is not destructed or freed. Hopefully you have a pointer to it stored somewhere else in your program (as in, you copied pa to some other variable with a bigger scope). You're gonna have to tell the compiler to destruct the object and free the memory at some point in the future. Otherwise, you get a memory leak.
Simply put, the "delete" command is only for objects allocated on the heap, because that's the manual memory management interface in C++ - new/delete. It is a command for the heap allocator, and the heap allocator doesn't know anything about stack allocated objects. If you try to call delete on a stack allocated object, you might as well have called it on a random memory address - they're the same thing as far as the heap allocator is concerned. Very much like trying to access an object outside array bounds:
int a[10];
std::cout << a[37] << "\n"; // a[37] points at... ? no one knows!
It just isn't meant to do that :)
Edit:
P.S. Memory leaks are more important when you are allocating memory in a function other than main. When the program ends, leaked memory gets deallocated, so a memory leak in main might not be a big deal, depending on your scenario. However, destructors never get called on leaked objects. If the destructor does something important, like closing a database or a file, then you might have a more serious bug on your hands.
stack memory is not being managed on the same way as heap memory.
there is no point to delete objects from stack: they will be deleted
automatically upon end of scope/function.
I'm trying to gain some memory saving in a C++ program and I want to know if I can use blocks as a scope for variables (as in Perl). Let's say I have a huge object that performs some computations and gives a result, does it makes sense to do:
InputType input;
ResultType result;
{
// Block of code
MyHugeObject mho;
result = mho.superHeavyProcessing();
}
/*
My other code ...
*/
Can I expect the object to be destroyed when exiting the block?
Yes, you can.
The destructor will be called as soon as the variable falls out of scope and it should release the heap-allocated memory.
Yes absolutely, and in addition to conserving memory, calling the destructor on scope exit is often used where you want the destructor to actually do something when the destructor is called (see RAII). For example, to create a scope based lock and release easily it in an exception safe way, or to let go of access to a shared or precious resource (like a file handle / database connection) deterministically.
-Rick
Just remember that any memory you allocate on the heap using new/malloc that is freed in the destructor probably won't be released back to the OS. Your process may hold onto it and the OS won't get it back until the process terminates.
Yes. It will be destroyed at the closing curly brace. But beware of allocating very large objects on the stack. This can causes a stack overflow. If you object also allocates large amounts memory, make sure it is heap allocated with new, malloc, or similar.