If I have the following:
Do I need to add "delete var" in the catch block? I would fire up valgrind if I had a working linux OS.Code:try
{
var = new myclass();
}
catch (std::exception& e)
{
std::cout << e.what() << std::endl;
return -1;
}
Printable View
If I have the following:
Do I need to add "delete var" in the catch block? I would fire up valgrind if I had a working linux OS.Code:try
{
var = new myclass();
}
catch (std::exception& e)
{
std::cout << e.what() << std::endl;
return -1;
}
Nope. The exception, I'm assuming, occurs inside myclass(). If this is so, it will occur before the assignment -- var never gets a value. You have nothing to free.
Now, internally, the class's constructor must make sure to deallocate anything that needs deallocation. Members inside the class will have their destructors called, but the class itself will not (if an exception occurs during the constructor.) Here's a test:
Code:#include <iostream>
#include <stdexcept>
class B
{
public:
B() { std::cout << "B created!" << std::endl; }
~B() { std::cout << "B destroyed... :-(" << std::endl; }
};
class A
{
public:
A() { throw std::runtime_error("BOOM."); }
~A() { std::cout << "A destroyed." << std::endl; }
private:
B m_b;
};
int main()
{
A *a = NULL;
try
{
a = new A();
}
catch(std::exception &e)
{
std::cout << "e.what() = " << e.what() << std::endl;
std::cout << "a = " << a << std::endl;
}
return 0;
}
>> Do I need to add "delete var" in the catch block?
If, however, you add any code after the call to new, then yes, you need to delete var inside the catch block (and make sure it is initialized to 0 before you call new so that if an exception occurs before that assignment the delete has no effect).
A better solution is to use RAII. Which smart pointer is right for the job depends on how you are using the variable and how long you want it to live. In the simple example you showed, you could use auto_ptr from the standard library, but in such a simple example you probably don't need dynamic memory anyway.
Don't forget to consider the case where it doesn't throw. Then you'll still need to do the manual cleanup otherwise you would leak. Thus it's better to use a smart pointer anyway.
But really, you need to show more code. There are ways those exact lines of code could happen to not leak, even if there was no exception thrown.
Adding delete var; in the catch block couldn't hurt if var was set to NULL before the try block. That way if you add extra code in the try block later, you don't have to remember to add the delete, since it's already there.
But smart pointers might be a better way to go anyways.
In other languages like C# and Java there is a
Unfortunately, C++ doesn't have that. So yes if you were to allocate memory and the program has an exception then the Operating System has to deallocate the memory I believe.Code:try {
Something
} catch(Exception e){
} finally {
delete ....;
file.close();
}
But fortunately it has RAII:Quote:
Unfortunately, C++ doesn't have that.
It is good to know how to do manual memory management, but in practice you should rarely need to do it (unless you are implementing really low level classes). In particular, exceptions and naked pointers don't match well.Code:try {
file = std::ifstream(somefile);
shared_ptr<X> xp(new X);
...
} catch (std::exception& ) {
...
}
//look, no finally!
Thanks guys for your input. I need this kind of input because I have no idea of the capabilities of C++ and these kind of threads really help me. I think I would like to focus on RAII as my design pattern, so thank you for the tips.
There may not be a need, but it would certainly be nice to have a finally keyword. It would save you from having to create a RAII class for every little thing that you want to happen if an exception is thrown (like closing files or DB connections or just writing to a log file...).
>> like closing files or DB connections or just writing to a log file...
I don't necessarily disagree with your sentiment, but those are poor examples, IMO. They are exactly the types of things RAII is best at.
I believe cpjust is sick of creating a new class for all kinds of different code.
So instead of having a finally statement, we'd have to create a new task to execute the code in RAII form instead of the final keyword.
Well, don't worry, cpjust. C++0x is going to fix that.
All we need to do is create a RAII class that executes a functor and embed a lambda that is our finally block.
I might be tired today, but fail to see how that addresses cpjust's concern about needing to create a RAII class.
Personally, I consider that providing a class (eg a sentinel) to encapsulate cleanup code is vastly superior to a finally block. But, then again, it is very rarely I encounter a scenario where cleanup code is only needed in one place - so I consider the reusability of a class an advantage, and prefer to minimise the number of places in code where exceptions actually get caught.
But the issue here is that each function has unique code. Thus it may have to execute some unique code at places. This is what would would wrap in a RAII class. But then you would have to create a new class or function for this unique code for every function. That's a lot of classes and functions you must create to make this RAII work.
With the finally block, you don't have to create a new class or function to contain that code. Instead you put it inside the finally block, so the code is actually inside the function that needs it. But with lambdas, we can create this unique code inside the function that needs it and wrap it in a RAII class that calls a functor on destruction.
What about the use of Boost.ScopeExit?