The main issue of C ++ exception

Can anyone describe how to handle the following situation correctly:

wchar_t* buffer = new wchar_t[...]; if (!something) { throw std::runtime_error("Whatever"); // Now, at this point I'm leaking memory allocated for the 'buffer'. } // Perform actions. delete[] buffer; 

The obvious way to solve this means something like:

 if (!something) { delete[] buffer; throw std::runtime_error("Whatever"); } 

Now is that good? (I suspect so, but who knows :)


PS I understand that there is a much better way to do this - using boost::scoped_array or just std::wstring , which allows destructors to call the allocated memory, just curious.

+4
source share
5 answers

Your understanding is correct. Sample

 Acquire some resource Do something Release resource 

is fundamentally wrong, because Do something can potentially cause an exception and a resource leak. In addition, you must remember to free up a resource, which is a fertile source of error.

The correct way, as you indicate, is to always use an object whose destructor frees the resource. This is called the RAII name in C ++.

This means, for example. never using delete external destructors or never relying on manual closing of file descriptors, never unlock mutexes manually, etc. Learn about smart pointers and use them whenever you can.

Note that some languages โ€‹โ€‹(not C ++) provide a finally keyword that allows you to execute a block of instructions regardless of whether an exception is thrown. C ++ uses RAII, and you should never care about releasing a resource if you write the correct destructors.

I have a small utility there for C ++ 0x, which allows you to execute arbitrary code on block exit if you interact with poorly written (or C) libraries once or twice.

+8
source

Where is the catch ? If it is in the same area, delete can be processed there, otherwise your # 2 is the correct option. This assumes, of course, that you do not want to do it right, as you yourself mentioned in the PS ...

0
source

It depends on something. If evaluating something can throw an exception, no, that won't be good. You must take care of each resource you purchase, using either a stack of allocated variables (which are destroyed at the end of the area) or using various types of smart pointers (std, boost, take your pick library).

0
source

The correct way is to use the RAII pattern. Instead of using a raw pointer, you should wrap this in an object that handles the freeing of memory in its destructor, for example, std::wstring or std::unique_ptr .

0
source

If you explicitly use the expanded new, you will have to explicitly use the deletion. So in this case you need to catch the exception and then call delete.

As you say, the right way is to wrap the buffer in a C ++ class whose destructor will be called. For a simple buffer, the class with the least overhead is probably std :: vector, but a smart pointer, for example. boost :: scoped_ptr will work too.

0
source

All Articles