Is this a good way to implement a Finally-like behavior in standard C++?
(Without special pointers)
class Exception : public Exception
{ public: virtual bool isException() { return true; } };
class NoException : public Exception
{ public: bool isException() { return false; } };
Object *myObject = 0;
try
{
// OBJECT CREATION AND PROCESSING
try
{
myObject = new Object();
// Do something with myObject.
}
// EXCEPTION HANDLING
catch (Exception &e)
{
// When there is an excepion, handle or throw,
// else NoException will be thrown.
}
throw NoException();
}
// CLEAN UP
catch (Exception &e)
{
delete myObject;
if (e.isException()) throw e;
}
No exception thrown by object -> NoException -> Object cleaned up
Exception thrown by object -> Handled -> NoException -> Object cleaned up
Exception thrown by object -> Thrown -> Exception -> Object cleaned up -> Thrown
The standard answer is to use some variant of resource-allocation-is-initialization abbreviated RAII. Basically you construct a variable that has the same scope as the block that would be inside the block before the finally, then do the work in the finally block inside the objects destructor.
try {
// Some work
}
finally {
// Cleanup code
}
becomes
class Cleanup
{
public:
~Cleanup()
{
// Cleanup code
}
}
Cleanup cleanupObj;
// Some work.
This looks terribly inconvenient, but usually there's a pre-existing object that will do the clean up for you. In your case, it looks like you want to destruct the object in the finally block, which means a smart or unique pointer will do what you want:
std::unique_ptr<Object> obj(new Object());
or modern C++
auto obj = std::make_unique<Object>();
No matter which exceptions are thrown, the object will be destructed. Getting back to RAII, in this case the resource allocation is allocating the memory for the Object and constructing it and the initialization is the initialization of the unique_ptr.
No. The Standard way to build a finally like way is to separate the concerns (http://en.wikipedia.org/wiki/Separation_of_concerns) and make objects that are used within the try block automatically release resources in their destructor (called "Scope Bound Resource Management"). Since destructors run deterministically, unlike in Java, you can rely on them to clean up safely. This way the objects that aquired the resource will also clean up the resource.
One way that is special is dynamic memory allocation. Since you are the one aquiring the resource, you have to clean up again. Here, smart pointers can be used.
try {
// auto_ptr will release the memory safely upon an exception or normal
// flow out of the block. Notice we use the "const auto_ptr idiom".
// http://www.gotw.ca/publications/using_auto_ptr_effectively.htm
std::auto_ptr<A> const aptr(new A);
}
// catch...
If for some strange reason you don't have access to the standard libraries, then it's very easy to implement as much as you need of a smart pointer type to handle the resource. It may look a little verbose, but it's less code than those nested try/catch blocks, and you only have to define this template once ever, instead of once per resource that needs management:
template<typename T>
struct MyDeletable {
explicit MyDeletable(T *ptr) : ptr_(ptr) { }
~MyDeleteable() { delete ptr_; }
private:
T *ptr_;
MyDeletable(const MyDeletable &);
MyDeletable &operator=(const MyDeletable &);
};
void myfunction() {
// it's generally recommended that these two be done on one line.
// But it's possible to overdo that, and accidentally write
// exception-unsafe code if there are multiple parameters involved.
// So by all means make it a one-liner, but never forget that there are
// two distinct steps, and the second one must be nothrow.
Object *myObject = new Object();
MyDeletable<Object> deleter(myObject);
// do something with my object
return;
}
Of course, if you do this and then use RAII in the rest of your code, you'll eventually end up needing all the features of the standard and boost smart pointer types. But this is a start, and does what I think you want.
The try ... catch approach probably won't work well in the face of maintenance programming. The CLEAN UP block isn't guaranteed to be executed: for example if the "do something" code returns early, or somehow throws something which is not an Exception. On the other hand, the destructor of "deleter" in my code is guaranteed to be executed in both those cases (although not if the program terminates).
My advice is: don't try to emulate the behaviour of a try-finally clause in C++. Just use RAII instead. You'll live happier.
Assuming you are looking to delete the pointer myObject and avoid memory leaks, your code can still fail to do this if there is a "return" statement in the code where you say // Do something with myObject. (I am assuming real code would be here)
RAII techniques have the relevant action that is equivalent to a "finally" block, in a particular object's destructor:
class ResourceNeedingCleanup
{
private:
void cleanup(); // action to run at end
public:
ResourceNeedingCleanup( /*args here*/) {}
~ResourceNeedingCleanup() { cleanup(); }
void MethodThatMightThrowException();
};
typedef boost::shared_ptr<ResourceNeedingCleanup> ResourceNeedingCleanupPtr;
// ref-counted smart pointer
class SomeObjectThatMightKeepReferencesToResources
{
ResourceNeedingCleanupPtr pR;
void maybeSaveACopy(ResourceNeedingCleanupPtr& p)
{
if ( /* some condition is met */ )
pR = p;
}
};
// somewhere else in the code:
void MyFunction(SomeObjectThatMightKeepReferencesToResources& O)
{
ResourceNeedingCleanup R1( /*parameters*/) ;
shared_ptr<ResourceNeedingCleanup> pR2 =
new ResourceNeedingCleanup( /*parameters*/ );
try
{
R1.MethodThatMightThrowException();
pR2->MethodThatMightThrowException();
O->maybeSaveACopy(pR2);
}
catch ( /* something */ )
{
/* something */
}
// when we exit this block, R1 goes out of scope and executes its destructor
// which calls cleanup() whether or not an exception is thrown.
// pR2 goes out of scope. This is a shared reference-counted pointer.
// If O does not save a copy of pR2, then pR2 will be deleted automatically
// at this point. Otherwise, pR2 will be deleted automatically whenever
// O's destructor is called or O releases its ownership of pR2 and the
// reference count goes to zero.
}
I think I have the semantics correct; I haven't used shared_ptr much myself, but I prefer it to auto_ptr<> -- a pointer to an object can only be "owned" by one auto_ptr<>. I've used COM's CComPtr and a variant of it that I've written myself for "regular" (non-COM) objects that is similar to shared_ptr<> but has Attach() and Detach() for transfer of pointers from one smart pointer to another.
To directly answer your question, no.
It's a clever way to implement that functionality, but it is not reliable. One way that will fail you is if your "do something" code throws an exception that is not derived from Exception. In that case, you will never delete myObject.
There's a more important issue at hand here, and that's the methodologies adopted by programmers of any particular language. The reason you're hearing about RAII is because programmers with much more experience than you or I have found that in the domain of C++ programming, that methodology is reliable. You can rely on other programmers using it and other programmers will want to rely on you using it.
Related
I'm trying to implement the Observer pattern, but i don't want observers being responsible for my program safety by maintaining the reference list in ObservableSubject.
Meaning that when the Observer object lifetime ends, I dont want to explicitly call ObservervableSubject::removeObserver(&object).
I have come up with an idea to use use pointer references in ObservableSubject.
My question are: Is implementation described above and attempted below possible?
And what is happening in my program, how do i prevent dereferencing trash?
Apriori excuse: This is an attempt at understanding C++, not something that should have actual use or be prefered over other implementations.
My solution attempt:
// Example program
#include <iostream>
#include <string>
#include <vector>
class ObserverInterface {
public:
virtual ~ObserverInterface() {};
virtual void handleMessage() = 0;
};
class ObservableSubject
{
std::vector<std::reference_wrapper<ObserverInterface*>> listeners;
public:
void addObserver(ObserverInterface* obs)
{
if (&obs)
{
// is this a reference to the copied ptr?
// still, why doesnt my guard in notify protect me
this->listeners.push_back(obs);
}
}
void removeObserver(ObserverInterface* obs)
{
// todo
}
void notify()
{
for (ObserverInterface* listener : this->listeners)
{
if (listener)
{
listener->handleMessage();
}
}
}
};
class ConcreteObserver : public ObserverInterface {
void handleMessage()
{
std::cout << "ConcreteObserver: I'm doing work..." << std::endl;
}
};
int main()
{
ObservableSubject o;
{
ConcreteObserver c;
o.addListener(&c);
}
o.notify();
std::cin.get();
}
Line in ObservableSubject::notify() : Listener->handleMessage() throws the following exception:
Exception thrown: read access violation.
listener->**** was 0xD8BF48B. occurred
Your program has undefined behavior.
ObservableSubject o;
{
ConcreteObserver c;
o.addListener(&c); // Problem
}
c gets destructed when the scope ends. You end up storing a stale pointer in the list of listeners of o.
You can resolve the problem by defining c in the same scope as o or by using dynamically allocated memory.
ObservableSubject o;
ConcreteObserver c;
o.addListener(&c);
or
ObservableSubject o;
{
ConcreteObserver* c = new ConcreteObserver;
o.addListener(c);
}
When you use dynamically allocated memory, the additional scope is not useful. You might as well not use it.
ObservableSubject o;
ConcreteObserver* c = new ConcreteObserver;
o.addListener(c);
If you choose to use the second approach, make sure to deallocate the memory. You need to add
delete c;
before the end of the function.
Update, in response to OP's comment
You said:
Maybe i wasn't clear. Solving the lifetime/stale pointer problem was the intention of my solution. I know i have no problems if i have properly managed lifetime, or if i add detachObserver option on Observer destruction. I want to somehow be able to tell from the ObservableSubject if his list of Observers was corrupted, without the Observer explicitly telling that.
Since dereferencing an invalid pointer is cause for undefined behavior, it is essential that you track the lifetime of observers and make sure to update the list of observers when necessary. Without that, you are courting undefined behavior.
Note, I don't recommend the following approach, but I think it meets your requirements. You have a duplicated observer list. One is under control of the Observers, and the other, using weak pointers, is handled by the Observable object.
Make the Observer constructors private and use an ObserverFactory (which is their friend) to obtain a std::shared_ptr<Observer>. The factory has a map from raw pointers to reference wrappers to the associated shared pointer.
The listeners list becomes std::vector<std::weak_ptr<Observer>>. On list traversal, you try to lock the weak_ptr; if it succeeds, handle the message; if it fails, that is, you get nullptr, remove the weak pointer from the list.
When the listener no longer wants to listen, it tells the Factory to do a reset on its shared pointer and remove from the map. This step is rather ugly, as it is just a fancy delete this, normally a code smell.
I believe you can also do this with std::shared_from_this.
The plan is you move the maintenance away from the ObservableSubject back into the Observers.
// is this a reference to the copied ptr?
Yes, it is. It invokes undefined behaviour because the obs pointer variable goes out of scope at the end of the function, resulting in a dangling reference.
The whole idea doesn’t gain you anything. Even if you make the ref-to-pointer approach work correctly, you are depending on one thing: That that exact pointer variable is set to nullptr once the object dies. Essentially that’s the same problem as ensuring that no dangling pointers are held in listeners.
For a heap object: How do you make sure that nobody deletes the object through a different pointer? Or forgets to null the registered pointer? It’s even worse for stack objects like in your example. The object goes out of scope and dies automatically. There is no opportunity to null anything unless you introduce an additional pointer variable that you’d have to manage manually.
You could consider two general alternatives to your approach:
Make the relation bidirectional. Then whoever dies first (observable or observer) can notify the other party abouts its death in the destructor.
If you don’t like the bidirectionality a central, all-knowing orchestrator that decouples oberservers and observables works, too. Of course that introduces some kind of global state.
Real-life implementations usually go in the general direction of leveraging C++ destructors for deregistration. Have a look at Qt’s signal/slot mechanism, for example.
I was reading an article that stated due to something called RAII, you no longer needed to cleanup your code.
What prompted this research was I am currently coding something that requires cleanup before exiting the function.
For example, I have created a file, and mapped a view of a file.
Normally, I'd just use goto or do {break;} while(false); to exit. However, is it true this is no longer necessary with C++11?
I.e. no more
if( fail ) {
UnmapViewOfFile(lpMapView);
CloseHandle(hFileMap);
CloseHandle(hFile);
}
every few lines of code?
Does the compiler automatically wrap this up once the function exits? It just seems hard to believe that it actually cleans up function calls like the article said it did. (I may have misinterpreted it somehow.) What seems more likely is that it just cleans up created class libraries by calling their deconstructor from the C++ library.
EDIT: The article - from Wikipedia:
It doesn't necessarily state that it cleans up these function calls, but it does imply it does for C++ library function objects (such as FILE * , fopen, etc objects)
Does it work for WinAPI too?
C++ standard surely says nothing about usage of windows API functions like UnmapViewOfFile or CloseHandle. RAII is a programming idiom, you can use it or not, and its a lot older than C++11.
One of the reasons why RAII is recomended is that it makes life easier when working with exceptions. Destructors will always safely release any resources - mostly memory, but also handles. For memory your have classes in standard library, like unique_ptr and shared_ptr, but also vector and lots of other. For handles like those from WinAPI, you must write your own, like:
class handle_ptr {
public:
handle_ptr() {
// aquire handle
}
~handle_ptr() {
// release
}
}
Cleanup is still necessary, but due to the possibility of exceptions the code should not do cleanup simply by executing cleanup operations at the end of a function. That end may never be reached! Instead,
Do cleanup in destructors.
In C++11 it is particularly easy to any kind of cleanup in a destructor without defining a custom class, since it's now much easier to define a scope guard class. Scope guards were invented by Petru Marginean, who with Andrei Alexandrescu published an article about it in DDJ. But that original C++03 implementation was pretty complex.
In C++11, a bare bones scope guard class:
class Scope_guard
: public Non_copyable
{
private:
function<void()> f_;
public:
void cancel() { f_ = []{}; }
~Scope_guard()
{ f_(); }
Scope_guard( function<void()> f )
: f_( move( f ) )
{}
};
where Non_copyable provides move assignment and move construction, as well as default construction, but makes copy assignment and copy construction private.
Now right after successfully acquiring some resource you can declare a Scope_guard object that will guaranteed clean up at the end of the scope, even in the face of exceptions or other early returns, like
Scope_guard unmapping( [&](){ UnmapViewOfFile(lpMapView); } );
Addendum:
I should better also mention the standard library smart pointers shared_ptr and unique_ptr, which take care of pointer ownership, calling a deleter when the number of owners goes to 0. As the names imply they implement respectively shared and unique ownership. Both of them can take a custom deleter as argument, but only shared_ptr supports calling the custom deleter with the original pointer value when the smart pointer is copied/moved to base class pointer.
Also, I should better also mention the standard library container classes such as in particular vector, which provides a dynamic size copyable array, with automatic memory management, and string, which provides much the same for the particular case of array of char uses to represent a string. These classes free you from having to deal directly with new and delete, and get those details right.
So in summary,
use standard library and/or 3rd party containers when you can,
otherwise use standard library and/or 3rd party smart pointers,
and if even that doesn't cut it for your cleanup needs, define custom classes that do cleanup in their destructors.
As #zero928 said in the comment, RAII is a way of thinking. There is no magic that cleans up instances for you.
With RAII, you can use the object lifecycle of a wrapper to regulate the lifecycle of legacy types such as you describe. The shared_ptr<> template coupled with an explicit "free" function can be used as such a wrapper.
As far as I know C++11 won't care of cleanup unless you use elements which would do. For example you could put this cleaning code into the destructor of a class and create an instance of it by creating a smart-pointer. Smart-pointers delete themselves when they are not longer used or shared. If you make a unique-pointer and this gets deleted, because it runs out of scope then it automatically calls delete itself, hence your destructor is called and you don't need to delete/destroy/clean by yourself.
See http://www.cplusplus.com/reference/memory/unique_ptr/
This is just what C++11 has new for automatically cleaning. Of course an usual class instance running out of scope calls its destructor, too.
No!
RAII is not about leaving clean-up aside, but doing it automatically. The clean-up can be done in a destructor call.
A pattern could be:
void f() {
ResourceHandler handler(make_resource());
...
}
Where the ResourceHandler is destructed (and does the clean-up) at the end of the scope or if an exception is thrown.
The WIN32 API is a C API - you still have to do your own clean up. However nothing stops you from writing C++ RAII wrappers for the WIN32 API.
Example without RAII:
void foo
{
HANDLE h = CreateFile(_T("C:\\File.txt"), FILE_READ_DATA, FILE_SHARE_READ,
NULL, OPEN_ALWAYS, 0, NULL);
if ( h != INVALID_HANDLE_VALUE )
{
CloseHandle(h);
}
}
And with RAII:
class smart_handle
{
public:
explicit smart_handle(HANDLE h) : m_H(h) {}
~smart_handle() { if (h != INVALID_HANDLE_VALUE) CloseHandle(m_H); }
private:
HANDLE m_H;
// this is a basic example, could be implemented much more elegantly! (Maybe a template param for "valid" handle values since sometimes 0 or -1 / INVALID_HANDLE_VALUE is used, implement proper copying/moving etc or use std::unique_ptr/std::shared_ptr with a custom deleter as mentioned in the comments below).
};
void foo
{
smart_handle h(CreateFile(_T("C:\\File.txt"), FILE_READ_DATA, FILE_SHARE_READ,
NULL, OPEN_ALWAYS, 0, NULL));
// Destructor of smart_handle class would call CloseHandle if h was not NULL
}
RAII can be used in C++98 or C++11.
I really liked the explanation of RAII in The C++ Programming Language, Fourth Edition
Specifically, sections 3.2.1.2, 5.2 and 13.3 explain how it works for managing leaks in the general context, but also the role of RAII in properly structuring your code with exceptions.
The two main reasons for using RAII are:
Reducing the use of naked pointers that are prone to causing leaks.
Reducing leaks in the cases of exception handling.
RAII works on the concept that each constructor should secure one and only one resource. Destructors are guaranteed to be called if a constructor completes successfully (ie. in the case of stack unwinding due to an exception being thrown). Therefore, if you have 3 types of resources to acquire, you should have one class per type of resource (class A, B, C) and a fourth aggregate type (class D) that acquires the other 3 resources (via A, B & C's constructors) in D's constructor initialization list.
So, if resource 1 (class A) succeeded in being acquired, but 2 (class B) failed and threw, resource 3 (class C) would not be called. Because resource 1 (class A)'s constructor had completed, it's destructor is guaranteed to be called. However, none of the other destructors (B, C or D) will be called.
It does NOT cleanup `FILE*.
If you open a file, you must close it. I think you may have misread the article slightly.
For example:
class RAII
{
private:
char* SomeResource;
public:
RAII() : SomeResource(new char[1024]) {} //allocated 1024 bytes.
~RAII() {delete[] SomeResource;} //cleaned up allocation.
RAII(const RAII& other) = delete;
RAII(RAII&& other) = delete;
RAII& operator = (RAII &other) = delete;
};
The reason it is an RAII class is because all resources are allocated in the constructor or allocator functions. The same resource is automatically cleaned up when the class is destroyed because the destructor does that.
So creating an instance:
void NewInstance()
{
RAII instance; //creates an instance of RAII which allocates 1024 bytes on the heap.
} //instance is destroyed as soon as this function exists and thus the allocation is cleaned up
//automatically by the instance destructor.
See the following also:
void Break_RAII_And_Leak()
{
RAII* instance = new RAII(); //breaks RAII because instance is leaked when this function exits.
}
void Not_RAII_And_Safe()
{
RAII* instance = new RAII(); //fine..
delete instance; //fine..
//however, you've done the deleting and cleaning up yourself / manually.
//that defeats the purpose of RAII.
}
Now take for example the following class:
class RAII_WITH_EXCEPTIONS
{
private:
char* SomeResource;
public:
RAII_WITH_EXCEPTIONS() : SomeResource(new char[1024]) {} //allocated 1024 bytes.
void ThrowException() {throw std::runtime_error("Error.");}
~RAII_WITH_EXCEPTIONS() {delete[] SomeResource;} //cleaned up allocation.
RAII_WITH_EXCEPTIONS(const RAII_WITH_EXCEPTIONS& other) = delete;
RAII_WITH_EXCEPTIONS(RAII_WITH_EXCEPTIONS&& other) = delete;
RAII_WITH_EXCEPTIONS& operator = (RAII_WITH_EXCEPTIONS &other) = delete;
};
and the following functions:
void RAII_Handle_Exception()
{
RAII_WITH_EXCEPTIONS RAII; //create an instance.
RAII.ThrowException(); //throw an exception.
//Event though an exception was thrown above,
//RAII's destructor is still called
//and the allocation is automatically cleaned up.
}
void RAII_Leak()
{
RAII_WITH_EXCEPTIONS* RAII = new RAII_WITH_EXCEPTIONS();
RAII->ThrowException();
//Bad because not only is the destructor not called, it also leaks the RAII instance.
}
void RAII_Leak_Manually()
{
RAII_WITH_EXCEPTIONS* RAII = new RAII_WITH_EXCEPTIONS();
RAII->ThrowException();
delete RAII;
//Bad because you manually created a new instance, it throws and delete is never called.
//If delete was called, it'd have been safe but you've still manually allocated
//and defeated the purpose of RAII.
}
fstream always did this. When you create an fstream instance on the stack, it opens a file. when the calling function exists, the fstream is automatically closed.
The same is NOT true for FILE* because FILE* is NOT a class and does NOT have a destructor. Thus you must close the FILE* yourself!
EDIT: As pointed out in the comments below, there was a fundamental problem with the code above. It is missing a copy constructor, a move constructor and assignment operator.
Without these, trying to copy the class would create a shallow copy of its inner resource (the pointer). When the class is destructed, it would have called delete on the pointer twice! The code was edited to disallow copying and moving.
For a class to conform with the RAII concept, it must follow the rule for three: What is the copy-and-swap idiom?
If you do not want to add copying or moving, you can simply use delete as shown above or make the respective functions private.
Given a situation where I want to have a stack allocated object that may throw during construction, but want to handle the exception at the calling site, how do I make the object accessible from outside the try block where it is constructed?
Eg
class MyThrowingClass {
MyThrowingClass() {throw exception();}
doSomethingImportant() {
//...
}
};
int main() {
//Need to catch the exception:
try {
MyThrowingClass myObj;
} catch() {
//actually handle the error
//...
}
//Also need to use myObj later on
myObj.doSomethingImportant();//but we can't use it here because it was scoped to the try block...
}
If I have myObj encased in a try then nothing outside the scope of the try can see it, but I don't want to have everything else inside there because then the code becomes 30 levels of nested try blocks, which is what the exception handling is supposed to remove with using the alternative of init function error codes.
I can't handle the exception inside the constructor as the reaction to the exception depends on the context of the use of MyThrowingClass.
Obviously the problem could be circumvented by having a
MyThrowingClass* pMyObj;
and then being able to wrapper the
pMyObj = new MyThrowingClass();
but surely this should be achievable with a stack allocated object too?
Is the only solution to do something like
MyThrowingClass myObj;
try {
myObj.init();
} catch(...) {
//...
}
at which point we're back to basically as bad as error codes and having an uninitialised or partially initialised object.
Note that this is not intended to be a global object, I want to have something that will be instantiated in many places.
Is it really the ideal solution to have a try block that wraps the entire scope (here everything that would be inside main) and catches that handle every possible exception at the end of that one try block as opposed to being able to handle exceptions vaguely near to their site?
int main() {
try {
//absoultely everything
}
catch (exceptionTypeA &a) {
//...
}
catch exceptionTypeB &b) {
}
}
how do I make the object accessible from outside the try block where it is constructed?
If construction fails, then the object doesn't exist; so there's nothing to access.
surely this should be achievable with a stack allocated object too?
Automatic (i.e. stack-allocated) objects are only initialised once, so even if you handle the exception, there's no way to go back and try to re-initialise it. If you do want to be able to retry, then you'll have to use something more complicated, like the dynamic allocation or two-stage initialisation you propose. Another alternative is something boost::optional (or, from next year, std::optional), which allows you to create and destroy objects at will within a lump of automatic storage.
Is it really the ideal solution to have a try block that wraps the entire scope?
In the typical case, where exceptions aren't handled locally and initialisation failure indicates an unrecoverable error, yes. In your special case, where you can handle it locally and recover, no.
try is designed to scope objects that can throw for a reason. By working around it, you are circumventing that which it's trying to protect you from (using a poorly defined object.) Consider using a function to generate the object. By using a noexcept move constructor, you can guarantee that the move out of the object is safe:
class MyThrowingClass {
public:
MyThrowingClass() {
throw exception();
}
// throw() is *okay* if you don't have noexcept
MyThrowingClass(const MyThrowingClass && other) noexcept {
}
};
MyThrowingClass GetObj() {
try {
return std::move(MyThrowingClass());
} catch(...) {
// return some well defined default or terminate program
}
}
int main() {
MyThrowingClass myObj(std::move(GetObj()));
}
Given a situation where I want to have a stack allocated object that may throw during construction, but want to handle the exception at the calling site, how do I make the object accessible from outside the try block where it is constructed?
Basically, you can't. As for wrapping ALL the code in a try block being a good or bad idea, that depends on the size of "all the code" - a dozen lines or so lines is no big deal.
Do you really want to call MyThrowingClass::doSomethingImportant() if the initialiser throws? Unless you somehow guarantee to fix the broken initialisation in the catch you're then calling methods on a partially initialised object.
Including the call to doSomethingImportant() in the same try block as the construction of the object would give you exactly what exceptions are designed to do: in the event of a problem skip past the following code (which is dependent on the preceding code) to an error handler.
I will use library in a huge project where exceptions are used for error handling. The library uses return codes for their error handling, meaning all functions will return a constant, defining if the function succeeded or any error happened.
Very often my functions have to abort if the library functions fail. Any better way to handle these errors than in the example implementation as given on the following snippet?
A main concern of my question is about deallocating previously allocated memory after each evaluation of the return code. This is fault-prone and cumbersome. I hope to find some guideline to prevent the deallocation at each call of the library functions...
void examplefunc()
{
T* pT = new T();
U* pU = new U();
Q myQ;
int iRes = CONST_SUCCESS;
if ((iRes = myQ.func1())!= CONST_SUCCESS)
{
delete pU;
delete pT;
throw translateException(iRes); // providing exc
}
if ((iRes = mQ.func2())!= CONST_SUCCESS)
{
delete pU;
delete pT;
throw translateException(iRes); // providing exc
}
delete pU;
delete pT;
return;
}
Thank you for all advice. Are there any guidelines I could follow?
Best regards
Sam
Use smart pointers. E.g. instead of:
T* pT = new T();
you might use C++11's unique_ptr:
std::unique_ptr<T> pT = make_unique<T>();
unique_ptr provides automatic destruction of the internal pointer as soon as the wrapping object gets out of scope.
You should create some sort of wrapper for the 3rd-party code.
Best practice is to never use the 3rd party code directly, as if it changes you will be forced to perform many changes.
For reference (in case you haven't seen it before), here's the C++11 version that uses smart pointers. It's equivalent to your code other than:
it doesn't leak pT in the case where new U() throws
likewise it doesn't leak if anything else throws (constructor of Q etc)
it destroys myQ before deleting pU and then pT, whereas your code deletes those first and then destroys myQ.
Typically the order of destruction doesn't matter, but it's something to be aware of in case it does matter. If you need to destroy your objects in anything other than reverse order of creation then their lifetimes can't be controlled simply by their scope.
void examplefunc()
{
std::unique_ptr<T> pT(new T());
std::unique_ptr<U> pU(new U());
Q myQ;
int iRes;
if ((iRes = myQ.func1())!= CONST_SUCCESS)
{
throw translateException(iRes); // providing exc
}
if ((iRes = mQ.func2())!= CONST_SUCCESS)
{
throw translateException(iRes); // providing exc
}
return;
}
I'm assuming of course that the T and U objects can't simply be placed on the stack -- you haven't shown why not, but the fact you're asking suggests there's a reason!
This code should not cause any issue at all with mixing raw and smart pointers between new and old code -- this function was previously responsible for freeing what it allocates, and it still is. If you need to pass a pointer to the T or U objects to some pre-existing code that takes a raw pointer:
without ownership, then pass pT.get()
with ownership (if this function isn't always responsible for deleting, because sometimes it passes or returns the pointer to someone else with that responsibility), then pass pT.release().
Then you can use smart pointers in more of your existing code as and when you like.
Finally, it's possible to write the above code in C++03 with std::auto_ptr, but you do have to be quite careful with auto_ptr, it's fairly easy to make mistakes with it. unique_ptr is "safer" but can't be fully implemented in C++03. boost::scoped_ptr is probably the best bet in C++03 if you don't need release().
Why don't you make pT and pU smart pointers (std::auto_ptr in C++98 or std::unique_ptr in C++11), throw the errors when you detect them and let the smart pointers do their work on their destruction (that will take place on exception, too).
Construct T and U on the stack instead of from the heap. Then they get deconstructed automatically. You should do this whenever you possibly can.
If you don't want to repeat the same stuff over and over write a function that does:
void throwErrorAndCleanup(T* pT, U* pU, int iRes)
{
delete pU;
delete pT;
throw translateException(iRes);
}
Another way to do this is with goto's. Using goto is a somewhat highly debated topic, however for error cleanup like this it often makes sense (in particular you may find that you need to cleanup more things as the function progresses, so you can create more jump targets that cleanup the extra stuff and then fall into the earlier cleanup).
void examplefunc()
{
T* pT = new T();
U* pU = new U();
Q myQ;
int iRes = CONST_SUCCESS;
if ((iRes = myQ.func1())!= CONST_SUCCESS)
{
goto error;
}
if ((iRes = mQ.func2())!= CONST_SUCCESS)
{
goto error;
}
delete pU;
delete pT;
return;
error:
delete pU;
delete pT;
throw translateException(iRes); // providing exc
}
As I understand it, when a new class is instantiated in C++, a pointer to the new class is returned, or NULL, if there is insufficient memory. I am writing a class that initializes a linked list in the constructor. If there is an error while initializing the list, I would like the class instantiator to return NULL.
For example:
MyClass * pRags = new MyClass;
If the linked list in the MyClass constructor fails to initialize properly, I would like pRags to equal NULL. I know that I can use flags and additional checks to do this, but I would like to avoid that, if possible.
Does anyone know of a way to do this?
The common approach here is to throw an exception (and handle it somewhere higher up).
One of the benefits of the exception mechanism is that it allows you to throw an exception from within a class constructor. In that case, you never reach the situation where a pointer is returned to the invalid. You would "get control" at the corresponding catch block. If the pointer was only declared within the try block (or in some other method invoked by the try block), it would be outside your scope in that catch block.
That is not a hack - it is quite legitimate and a common programming technique.
For example, if your class constructor allocates memory dynamically (e.g., for an internal buffer) and this allocation failed, you would want to throw an exception because at the end of the constructor body you would not have a valid object.
Here is an example (I've been doing Java for the past 10 years, so my C++ code below is likely messed up here, maybe someone can edit this for me)
// Begin C++ code written by a Java programmer... :)
class Myclass
{
public:
Myclass(int length)
{
if(length<=0) throw BadBufferSizeException("Bla bla bla");
this->buffer = (char*)malloc(length*sizeof(char)); // don't remember the new syntax
}
void doSomething()
{
// Code for placing stuff in the buffer
}
private:
char* buffer;
};
int main()
{
try
{
int len;
len = getLengthFromUser();
MyClass* pMyClass = new MyClass(len);
myClass->doSomething();
} catch(const Exception & e)
{
// Whatever... Note how pMyClass is not even accessible here
}
}
Note that if you defined pMyclass to be null outside the try block, and then only reassigned it within the try block when you create the class, in the case of failure you would likely still have null, but you would never have executed doSomething(). If you are concerned about initialization, you could also move the doSomething() call to outside the try-catch block, but you would want to make sure that your pointer is not null.
Also note that C++ gives you more (too much?) freedom when it comes to throwing things than other languages. I usually like having a hierarchy of exception classes or using an existing library with such a hierarchy.
The standard way for a constructor to indicate an error is with an exception.
If, for some reason, your application can't deal with exceptions and needs the NULL return value, you can wrap the constructor in factory method like this...
class MyClass
{
public:
static MyClass* makeMyClass()
{
MyClass* retval = NULL;
try
{
retval = new MyClass();
}
catch(std::exception& e)
{
// Report the exception;
retval = NULL;
}
return retval;
}
// ....
};
Your understanding is somewhat old, as the 1995 Standard prescribed the use of exceptions instead of returning 0. It also provided for a nothrow series of methods, which work as follows: Foo * foo = new (nothrow) Foo;.