Can anyone explain to me the point of RAII? - c++

So, if I understand correctly, the point of RAII is to remove the hassle of memory management. That is, you do the deleting in the destructor of the object. That way, when the pointer goes out of scope, you do not have to worry about deleting it. So here is what I don't understand: why not just declare the variable on the stack in the first place?

There are a few things wrong with your understanding:
The point of RAII is to remove the hassle of resource management, not just memory. For example: A file handle that needs to be closed, a mutex that needs to be unlocked, an object that needs to be released, memory that needs to be freed. Basically, if there is something you have to to when you finish using a resource, that's a good case for RAII.
When a raw C++ pointer goes out of scope, it does nothing. I assume you're talking about a smart pointer which is nothing but an object that wraps around a raw pointer. When that object goes out of scope, its destructor is called and the destructor can be used in turn to free the memory that was allocated in the constructor.
It does not make a difference whether the object that needs to be "released" was allocated on the stack or the heap. The point is that you do something in the constructor when you acquire the resource and you do something else in the destructor when you're finished with it.

You cannot declare a database connection or a window or a file on the stack. At least, it's arguable that that is exactly what RAII permits you to do, but without that, you can't.

The point of RAII is that the destructor will be invoked no matter how you exit the scope.
So whether you exit normally or by throwing an exception, your resource will be freed.
BTW, the "resource" doesn't have to be just memory - it can be a file handle, a database connection etc.

Related

release object's memory VS termination housekeeping?

I am studying a book called "C++ How to Program" by Paul Deitel, chapter 9 is talking about Classes, and I quote:
The destructor itself does not actually release the object's memory--it performs termination housekeeping before the object's
memory is reclaimed, so the memory may be reused to hold new objects.
so my question is, what does the Author mean by Termination housekeeping and releasing memory? and how different they are from each other? if they are any different.
What it means is the destructor function does not release memory, but it is a place where you can declare what housekeeping functions need to be done. For example, if your object owns pointers to other data that it should release, then it's time to delete those. For example if you had a pointer named owned that was given something to retain:
MyThing::~MyThing() {
delete owned;
}
This delete call will trigger the destructor for that owned object if it has one, which initiates this process all over again in a recursive manner.
You might also close file-handles, delete temporary files, whatever it is your object should do when tidying up. That might include deleting operating-system GUI elements as well, it really depends on where this code lives.
The destructor is called during the process of releasing memory, but it itself does not release any of its own memory. That action is performed after the destructor finishes.
There are other forms of cleanup besides releasing memory. Sometimes you may need to close a communications channel during the terminator of a class. Or you might release resources used for threading when a class closes. Or maybe you just modify a pointed to object.
The destructor is the code that runs when the object falls out of scope. There's nothing else to it.

Class destructors and pointer deallocation

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.

How to properly define destructor

I am relatively new to C++ (and programming in general) so please forgive me if the question is not perfectly clear immediately.
What I have is a program in which a certain number of objects of a internally defined class [let's call this "class1"] are created.
The program works perfectly fine and the objects do what they should.
The problem that I am currently trying to solve is the following: these objects are not destroyed (and thus memory is not de-allocated) until the program exits, but I need that memory earlier.
Among the other members of the class there are objects of other internally defined classes (who also have members that are objects of a third class).
My question is the following: how do I properly define a destructor for the objects of "class1" so that all the data is cancelled and the memory deallocated?
I found out (probably this was obvious for you already) that a destructor like
class1::~class1(void) {
}
won't work (I defined similar destructors for all internally defined classes).
Reading around I understood that my mistake could be that that is a destructor that does nothing. How do I solve this?
Thanks to anyone who will answer/help/comment.
Federico
In C++ you need to free the memory manually. There's no garbage collector. You obviously need to free the memory manually inside your destructor. If you allocated the memory using new, you need to use delete for each resource you allocated with new inside the deconstructor, for example:
class1::~class1(void)
{
delete resource1;
delete resource2;
etc...
}
If you are allocating memory dynamically you need to free it in destructor, but better solution would be to use some smart pointer to hold dynamic data - std::auto_ptr or std::shared_ptr. Then you will not need to explicitly free memory - this will be done automatically in smart pointer destructor.
First you should try to allocate your objects on the stack:
Object obj;
so you don't have to worry about memory allocation. The disadvantage is that the object life is limited to the current scope.
If that's not good for you, you should consider using smart pointers. If that's not an option use new / delete to create / destroy your objects. But you have to be careful, every new should lead to a delete at some point in time..
Memory on stack
If there is no heap-allocated object inside your class, there is no need for you to explicitly define the destructor of your class. The compiler-generated one should handle the job quite well, i.e., call destructors for base class objects and member objects, etc.
Memory on heap - manual memory management
If there is any heap-allocated objects inside your class, you need manually deallocate them in your destructor. Make sure you have them deallocated properly at all possible exit points, e.g., handle exceptions and deallocate resources.
Memory on heap - RAII
Alternatively, you may use some well-defined RAII class to handle the resource management for you automatically, e.g., scoped_ptr, scoped_array in Boost, shared_ptr in STL, etc.

Do I need to delete an static std::map?

In some classes I have an static std::map with pointers inside. My question is if I need to delete at the end of the program or this memory is automatically freed. My concern is if the pointers stored inside are correctly deleted through our destructors when std::map is deleted.
Thanks.
If the map contains pointers that were allocated with new (or new[], or malloc), then each pointer needs a corresponding delete (or delete[], or free).
The map's destructor wont know what to do with a bald pointer. Consider using a smart pointer that has appropriate move semantics like a boost smart pointer or if you've got a very new compiler, one of the C++0x smart pointers. However, do not use the current standard's std::auto_ptr, inside of STL containers. See this thread for why.
Edit:
As Billy ONeal pointed out, boost::ptr_map is also designed exactly for this purpose.
If I understand the situation correctly, you don't delete the map itself. But you probably need to delete the objects the map is pointing to. It would probably be a really good idea to use a smart pointer such as Boost shared_ptr in your map instead of native pointers. Then the objects would be cleaned up automatically.
Edit:
Using Boost ptr_map might be an even better idea.
The memory is "automatically freed", in the sense that the entire process memory is freed, but the destructors of the objects pointed to will not be called. This can cause a resource leak, if you use RAII.
std::map never calls delete on it's members. Assuming you're working with a relatively recent operating system, the OS will reclaim the memory occupied by the members on process termination, but the destructors will not run.
If you have a map of pointers, then the answer is 'no', your destructors will not be called, but 'yes', the memory will be freed at the end of process execution. All memory allocated by a process is always freed by the Operating System when a process exits (even if it crashes), but destructors might not be called.
A memory "leak" is where memory is unintentionally not deleted over a period of time, and ends up reducing as the process continues. If it is a type of process that runs for a very long period of time, eg a server that is rarely restarted, this can be a major problem.
Memory leak detectors will pick up on any memory that is allocated and not deleted by a programming call, so valgrind, etc. will report this as a leak.
It is as well to check your code with programs like valgrind, and therefore the less that "gets in the way", the easier it will be to spot real leaks. Therefore my advice is not do just let the system clean up the memory, or singletons, etc, for you when you have allocated a pointer with new (or malloc or new[]).
You can have a "clean-up" routine to do this. Just have an object in the scope of your map that has a deleter (as it will be deleted when it exits) that will clean up the pointers in the map. As you need your object to be deleted first it should be declared later than the map.
Like in any case of storage class which stores pointers: you are responsible to deallocate memory they point to. Storage class is responsible only to clean its own resources. Relying on reclaiming memory by OS at the process termination is a bad practice.

would the memory pointed by auto_ptr leak in case of never ending application?

I need to run an application in an embedded system continuously. While implementing this application, i need to allocate lot of memory from Heap. If i use auto_ptr for those, when will that be freed ? As per my understanding, memory pointed by auto pointers would be freed upon exiting/terminating the application. It would not be freed automatically if application is not exited.
I can use reset() to free the memory like below.
auto_ptr<Test> testPtr(new Test);
testPtr.reset();
But then, the purpose of auto_ptr would be defeated if i do this. If i can do reset() at all places, i can do delete also at all the places.
Pls let me know whether memory pointed by auto_ptr would get freed even though application is not exited. If not, is there any otherway to freeup the memory, other than calling reset() ?
EDIT: In my case, auto_ptr is inside a class. That class object will be destroyed only upon exiting the application. As the application runs infinitely, class object will not be destroyed. Hence the issue. Pls consider this also.
EDIT: Answer: As i am using same auto_ptr for storing other objects, everytime i do assignment, auto_ptr assignment operator would take care of deleting previous object. So no leak even without call to reset.
auto_ptr gives you two things:
assignment transfers ownership
when an owning auto_ptr is destroyed, so is the data it owns
The application exiting only becomes relevant if/when you have global auto_ptr objects -- which rarely makes sense in the first place. A global auto_ptr referring to a dynamically allocated object can usually be replaced by by making the object itself global (but you generally want to avoid both).
For most normal uses of auto_ptr, exiting the application is irrelevant -- it's exiting the scope at which the auto_ptr is defined that matters. At that point, the object it owns gets deleted.
Memory pointed by auto_ptr is released when auto_ptr instance is destroyed. For local auto_ptr instance, defined in a function, this happens when function exits. If auto_ptr instance is class member, it is destroyed when container class instance is destroyed. Global auto_ptr instance is destroyed when the program exits.
The destructor for the auto_ptr class will invoke the delete operator on the pointer you specified when calling the constructor i.e. new Test. Invoking auto_ptr::reset() has the same effect.
The benefit is that you can use scope rules to automate the destruction of the object being pointed to by an auto_ptr instance.
In your example testPtr is being instantiated on the stack and will be destroyed once it is out of scope.
Consider this example:
void foo()
{
//... do some work
{
auto_ptr<Test> testPtr(new Test);
//... do something with testPtr
} // *at this point testPtr is no longer in scope and the pointer held by this object
// will be deleted
//... do some additional work
}
Now obviously you could have not bothered using scope (i.e. {}) and just called auto_ptr::reset() where I marked * but this method has the benefit of working in the presence of exceptions and return statements and so on.