Assume I have a function like this:
MyClass &MyFunction(void)
{
static MyClass *ptr = 0;
if (ptr == 0)
ptr = new MyClass;
return MyClass;
}
The question is at program exit time, will the ptr variable ever become invalid (i.e. the contents of that ptr are cleaned up by the exiting process)? I realize that this function leaks, but it is only an example for simplicity.
The same question also applies to other primitives besides pointers as well. How about if I have a static integer, does the value of that integer always persist throughout exit or is variable due to static destruction order issues?
EDIT:
Just to clarify, I want to know what actually happens to the contents of the static pointer (or any other primitive type like an int or a float) and not to the memory it is pointing to. For instance, imagine that the ptr points to some memory address which I want to check in the destructor of some other static class. Can I rely on the fact that the contents of the ptr won't be changed (i.e. that the pointer value won't be cleaned up during the static destruction process)?
Thanks,
Joe
When you process exits the all memory pages allocated to it will be freed by the OS (modulo shared memory pages that someone else may be using).
However, as others point out the destructor for MyClass is never called. Nor is the value pointed to by ptr ever changed. If you have a static int with the value 123 then its value will stay 123 through to the very end of the process' lifetime.
In modern operating systems, all of an application's memory is allocated on a "heap" specific to that application. When the application exits, all of the memory in that heap will be freed.
So, the memory will be deallocated, but: the destructor for MyClass will never be called. This can be an issue if the destructor is responsible for releasing any non-memory resources (file system locks are a common example).
To answer your question:
'imagine that the ptr points to some memory address which I want to check in the destructor of some other static class'
The answer is yes.
You can see the value of the pointer (the address).
You can look at the content if you have not called delete on the pointer.
Static function variables behave in the same way as static class variables and global variables (aka non local static), in that there destructors will be called in reverse order of creation. Integers, floats and pointers (POD) do not have destructors so nothing happens to them until the processes is removed.
POD objects: Data can safely by referenced from the destructor of other objects (even global s).
Other static objects (i.e. those with destructors): In the general case, it is not safe to accesses these objects after main() has exited because the order of destruction is not know (it is the reverse of the order of creation, but the order of creation is complex see: Construction Order ). It can be done but you have to take explicit precautions to make sure the object is still alive.
Note: non local static:
The memory will always be there, the object will just not be valid after a destructor is called (note POD does not have a destructor).
Note: Stack:
Only valid until the scope in which they are declared is left.
After the stack is popped the memory page that it is on could potentially be dropped resulting in SEG faults if you attempt to access it.
Note: Heap:
Valid until you call delete on the pointer that allocated it.
Once a pointer is delete the value is potentially random as it may be re-used.
Potentially the page the memory was on can also be dropped. Any access to a dropped page would result in a SEG fault.
To answer your updated question, I would say yes: you can rely on the value of that static pointer remaining throughout the static destruction process. The memory it points to may have been freed, but the value of the pointer itself should remain unchanged, unless the destructor of another static class makes a change to it.
The short answer is "no": your pointer will not "become invalid" at program exit time. I.e. the pointer value will not automatically be reset to null, and destructor of the MyClass object to which it points will not automatically be called.
This is because a pointer is a "primitive type", i.e. not an object.
If you have a non-local (i.e. global or static) variable which is an object, then the rules are different: the destructor of the object will be called when the program terminates by calling exit() or by returning from the main function. It will not be called if the program terminates by calling abort().
Related
I am writing a class (virtual_flight_runtime_environment), and it is mostly non-static, with the exception of one static function for the purposes of a Win32 thread using it as its function. The class declares struct simaircraftdata* aircraftdata (a data struct), and calls 'aircraftdata = new aircraftdata;' in the constuctor (public: virtual_flight_runtime_environment()).
My question is about destructors and memory deallocation. I have written the destructor as such:
~virtual_flight_runtime_environment(void) {
/*..Other code, i.e. closing win32 handles, etc.*/
delete aircraftdata;
}
Now, the class is declared in another function (the DoWork function of a .Net background worker) like so:
virtual_flight_runtime_environment* this_environment = new virtual_flight_runtime_environment;
And just before the end of the function, I call 'delete this_environment;'. Immediately after, 'this_environment' would have gone out of scope, and the desturctor should have been called.
Is this correct? I do notice continued increases in memory usage over time, and I'm wondering if I've done something wrong. Does calling delete on a pointer just make it a null pointer, or does it deallocate the data at the end of it?
Any advice would be appreciated,
Collin Biedenkapp
There is no direct connection between a delete in your program and whether it will directly be visible in say the task manager because the OS tries to optimize memory utilization. When you look in the task manager you will typically see the working set size of your application, this is a measure of how much memory your app has requested but not necessarily how much it is currently using.
And to your question, yes deleting the memory as you did it is the WTG although as others have pointed out using smart pointers is generally much better to handle memory to avoid later headaches.
You're almost correct.
delete this_environment calls the destructor of virtual_flight_runtime_environment. The destructor executes delete aircraftdata.
Right after that, the memory occupied by the instance of virtual_flight_runtime_environment is released.
Please be aware that delete statement doesn't set the pointer to NULL.
So I see no problem in your code given the information in the question.
This looks correct.
Calling delete on your this_environment will cause the destructor of that class to be called before it's memory is deallocated. The destructor deletes the aircraft data. Looks correct.
You might consider instead of having a member variable containing a raw pointer to aircraftdata instead using an auto_ptr or in c++11 unique_ptr which will ensure that it gets deleted automatically when it's containing class is constructed. Look it up, this isn't the place to teach it and it's just a suggestion, not a necessity.
Edit: And I also agree with Pete Becker's comment on the question, which is to question if this needs a pointer at all.
You should indeed explicitely call "delete this_environment". Otherwise, it's only the pointer itself (which exists on the stack) which would be destroyed. The data pointed, on the heap, would still exist.
The other solution is to simply get rid of the pointer and declare your variable as such :
virtual_flight_runtime_environment this_environment;
That way, your object will directly exist on the stack, and its lifetime will depend on the scope in which it is declared - and the destructor will be automatically called at this point, calling in turn the delete for your internal data.
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.
Just wondering, if I statically create an object that has a pointer as a data member and then the object goes out of scope, what happens to the pointer?
Chuma
Nothing happens to the pointer at all, it just ceases to exist. If it was pointing to something that needed to be freed, you just got a memory leak.
Either add code to the destructor that does the proper cleanup of the pointer, or use "smart pointers" that clean up after themselves automatically.
Edit: If you actually meant you were creating a static object, by declaring it with the static keyword inside a function, then the answer is different. A static object, once constructed by the first execution of the function that declares it, continues to live until the program ends. Its data members, including pointers, will remain valid. Subsequent calls to the function will access the same object. If the object has allocated any memory, it will remain allocated unless something explicitly deletes it.
The pointer gets destroyed with the rest of your object. Whatever it was pointing at isn't affected at all (unless the object's destructor does something with it).
Revised answer
There are two properties of a variable which are relevant here - scope and lifetime - and I think the question is conflating the two.
In all the contexts I can think of, a statically allocated object has a lifetime that is essentially the lifetime of the process. There are some technical details about exactly when the object is first initialized (constructed), but the net result is essentially the same - a statically allocated object exists for the duration of the process.
However, an object may come into scope, and go out of scope, as the thread of control moves between functions in the program. The scope of the object is where it is visible by name. It may be accessible elsewhere if a pointer to it (or reference to it) is passed to other functions where it would not otherwise be in scope.
Since a statically allocated object has a lifetime of the duration of the program, pointer members of that object do not change because the object goes out of scope; the object continues to exist unchanged, and the pointer members continue to point to the same place. Clearly, if a pointer in the statically allocated object points to a variable that had automatic duration and that pointed-to variable ceases to exist because it is destroyed, then the pointer in the statically allocated object points to an invalid location.
However, the key point is that the statically allocated object is not changed, and the pointer members are not changed, but changes in scope. And there are no leaks caused by the changes in scope.
Original answer
In all the contexts I can think of, a statically allocated object can't go out of scope, pretty much by definition. I suppose that if a shared library was loaded and then unloaded, then a statically allocated object might go 'out of scope', but otherwise...
If this premise is correct, then the second half of the question is easy. You can take either of two views:
Since the static object never goes out of scope, nothing happens to the static object and its pointer member, and it will be pointing to the same place when the object comes back into scope - where scope here means 'into a function that could access the static object'.
When the thread of control leaves a scope that could access the static object, nothing happens to the static object and its pointer member, and it will be pointing to the same place when the object next comes back into scope.
Which is basically saying the same thing, twice. If I said it a third time, it would automatically be true, wouldn't it? So, a statically allocated object doesn't go out of scope (even if it is not always accessible from the current function) and so nothing happens to the pointer members. There...what I said is so. I think!
What am I missing? Does 'statically created object' have a meaning I've not thought of?
I'm a C and Java programmer, so memory allocation and OOP aren't anything new to me. But, I'm not sure about how exactly to avoid memory leaks with C++ implementation of objects. Namely:
string s1("0123456789");
string s2 = s1.substr(0,3);
s2 now has a new string object, so it must be freed via:
delete &s2;
Right?
Moreover, am I correct to assume that I'll have to delete the address for any (new) object returned by a function, regardless of the return type not being a pointer or reference? It just seems weird that an object living on the heap wouldn't be returned as a pointer when it must be freed.
No.
You only need to free memory you allocate (i.e. via new or memalloc).
No,
Both s1 and s2 will get destructed when out of scope.
s1.substr() will create a temporary object that you don't have to think of.
There are a couple of layers to the answers.
First, variables can be declared in several different ways:
As local variables (either inside a function or as class members). Examples: int i, or int i = 42. These have automatic storage duration (these examples are technically shorthand for auto int i, or auto int i = 42, although the auto keyword is virtually never used. What this means is that these variables will be automatically freed when they go out of scope. Their destructor is guaranteed to be called (no matter how you leave the scope, whether it is by a function return or by throwing an exception, their destructor will be called when they go out of scope, and then the memory they use is freed). Local variables declared like this are allocated on the stack.
A static variables (with the static keyword, implying static storage duration, as opposed to automatic shown above. These just stay around for the duration of the program, and so don't have to be freed
on the heap, with dynamic allocation (new int or new int(42)). These have to be freed manually by calling delete.
So at the lowest level, you basically just have to preserve symmetry. If something was allocated with new, free it with delete,mallocis freed byfree, andnew[]bydelete[]`. And variables that are declared without any of these are automatically handled, and should not be manually freed.
Now, to keep memory management simple, RAII is typically used. The technique is based on the observation that only dynamically allocated objects have to be manually freed, and that local variables give you a very convenient hook for implementing custom actions when a local variable goes out of scope.
So, the dynamic allocation is wrapped up inside a separate class, which can be allocated as a local object on the stack. It can then, in its constructor, make any dynamic allocations you need, and its destructor cleans it up with the necessary delete calls.
This means that you essentially never have to call delete in your top-level code. It'll virtually always be hidden behind a RAII object's destructor. new calls become rare too, but are still used together with smart pointers (such as this: boost::shared_ptr<int>(new int(42)) which dynamically allocates an integer, and then passes it to a smart pointer which takes over ownership of it, and cleans it up automatically.
Both s1 and s2 are auto allocated. You don't delete those.
You only delete objects which you have created using new.
C++ knows three allocation modes: auto, static and dynamic. Read up on those.
Auto values, like your strings in the example are freed automatically when they leave scope. Their destructor is called automatically. Any memory that the strings allocated dynamically during their operation is freed when the string destructor is called.
Like everyone else said - no delete is needed here. Unless you see a new, you (generally) don't need a delete. I do want to add that s2 doesn't have a new string object. s2 is a string object from the time that it is declared. Assigning a slice of s1 to s2 modifies s2 so that it contains the same characters that are in the substring.
It's really important to understand what is going on here and it will become even more important the more you dig into C++. Oh, and congrats on learning a new language.
No, s2 does not need to be manually deleted. It is a local variable on the stack that will get automatically destroyed once it goes out of scope, just as it was automatically allocated when it was declared. Generally you only delete things that you allocated with new.
Temporary objects returned by functions are managed automatically and get destroyed by the end of the statement - if they are needed longer they get usually copied to a local variable before the temporary is destroyed (e.g. by a simple assignment like Object o = f(); or like in the line with the substr() call in your example).
If a function returns a pointer, the pointed-to object is not automatically managed like this. In the documentation should be noted who is responsible to delete the object once all work is done. As a default convention usually the one who allocated the object is responsible to delete it again, but the details need to be documented somewhere.
One of the most important concepts to understand in modern C++ (especially coming from a c background) is RAII. C++ encapsulates resources like memory (or mutexes, or transactions) inside classes that "acquire" the resource on construction (the string constructor allocates dynamic memory) and "release" it on destruction (destruction of the string class frees it). Since destruction of stack objects is deterministic (the stack based object expires when the enclosed scope does), the release doesn't have to be written, and will happen even if an exception is thrown.
So, no. In most of my coding, I never have a write an explicit delete (or delete[]), because either the resources are managed by string, an STL conatiner, or a shared_ptr or scoped_ptr.
why do you have to free s2 manually?
deletion of dynamic memory in s2 will be handled by the std::string destructor.
I was working on a piece of code and I was attacked by a doubt: What happens to the memory allocated to a pointer if I assign NULL to that pointer?
For instance:
A = new MyClass();
{...do something in the meantime...}
A = NULL;
The space is still allocated, but there is no reference to it. Will that space be freed later on, will it be reused, will it remain on stack, or what?
This is a classic leak.
As you say, the memory remains allocated but nothing is referencing it, so it can never be reclaimed - until the process exits.
The memory should be deallocated with delete - but using a smart pointer (e.g. std::auto_ptr or boost::shared_ptr (or tr1::shared_ptr) to wrap the pointer is a much safer way of working with pointers.
Here's how you might rewrite your example using std::auto_ptr:
std::auto_ptr a( new MyClass() );
/*...do something in the meantime...*/
a.reset();
(Instead of the call to reset() you could just let the auto_ptr instance go out of scope)
Under most circumstances, that will cause a memory leak in your process. You have several options for managing memory in C++.
Use a delete to manually free memory when you're done with it. This can be hard to get right, especially in the context of exception handling.
Use a smart pointer to manage memory for you (auto_ptr, shared_ptr, unique_ptr, etc.)
C++ does not come with a garbage collector, but nothing prevents you from using one (such as the Boehm GC) if you want to go down that route.
That is a memory leak. You have to delete memory you allocate manually.
A = new MyClass();
{...do something in the meantime...}
A = NULL;
The way I keep track of it is that there are two separate objects. Somewhere on the heap, a MyClass instance is allocated by new. And on the stack, there is a pointer named A.
A is just a pointer, there is nothing magical about out, and it doesn't have some special connection to the heap-allocated MyClass object. It just happens to point to that right now, but that can change.
And on the last line, that is exactly what happens. You change the pointer to point to something else. That doesn't affect other objects. It doesn't affect the object it used to point to, and it doesn't affect the object (if any) that it is set to point to now. Again, A is just a dumb raw pointer like any other. It might be NULL, or it might point to an object on the stack, or it might point to an object on the heap, or it might be uninitialized and point to random garbage. But that's all it does. It points, it doesn't in any way take ownership of, or modify, the object it points to.
You need to delete A;
For regular objects setting the pointer to NULL does nothing but invalidating the pointer, the object is still around in memory, this is particularly true if you notice that you may have more than one pointer to the same object, changing one shouldn't affect the others.
On most modern OSs, the application's memory will be reclaimed at exiting the application. Meanwhile, you have a memory leak.
As per Phil Nash's comment, for every new, there is a corresponding delete, likewise, for every malloc, there is a corresponding free. If the corresponding delete/free is not there, you have a leak.
Hope this helps,
Best regards,
Tom.
C++ does't have garbage collector, like some other languages has (Java, C#, ...) so you must delete allocaled objects yourself.
No, it will be lost to the process forever. You will have a memory leak. If you keep doing this, your program will eventually run out of memory!! To avoid this, delete the object when you no longer need it.
Often people will set the pointer to NULL after deleting it, so that other parts of the program can verify that the object has been deleted, and thereby avoid accessing or deleting it again.
Variables stored on the stack, are the local variables of each function, e.g. int big[10];
Variables stored on the heap, are the variables which you initiated using explicit memory allocation routines such as malloc(), calloc(), new(), etc.
Variables stored on the stack have a lifetime that is equal to the lifetime of the current stack frame. In English, when the function returns, you can no longer assume that the variables hold what you expect them to hold. That's why its a classic mistake to return a variable that was declared local in a function.
By assigning NULL to the pointer you will not free allocated memory. You should call deallocation function to free allocated memory. According to C++ Standard 5.3.4/8: "If the allocated type is a non-array type, the allocation function’s name is operator new and the deallocation function’s name is operator delete". I could suggest the following function to safely delete pointers (with assigning NULL to them):
template<typename T>
inline void SafeDelete( T*& p )
{
// Check whether type is complete.
// Deleting incomplete type will lead to undefined behavior
// according to C++ Standard 5.3.5/5.
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete p;
p = NULL;
}