简体   繁体   中英

How to safely release resources allocated by constructor?

I use C function which should write text to the buffer allocated in the constructor. The problem is that I need to pass a string to the exception constructor, but after creating an exception, the memory allocated for the text is lost:

class SomeClass{
public:
    SomeClass(){
        //important code ->
        //...
        //<- important code

        if(0 != some_func_to_get_error()){
            int bufferLen = some_func_to_get_buff_len();
            char* bufferText = new char[bufferLen + 1];
            some_func_to_get_text(bufferText, bufferLen); //contains error text
            throw runtime_error(bufferText); //exit from constructor body
            //???
        }
    }
};

Now the text is lost somewhere. Please tell me how to solve this problem.

I assume runtime_error in your code above refers to std::runtime_error ? In this case, you can simply pass it an std::string and release the buffer. For example

int bufferLen = some_func_to_get_buff_len();
auto bufferText = std::unique_ptr<char[]> { new char[bufferLen + 1] };
some_func_to_get_text(bufferText.get(), bufferLen);
throw runtime_error({ bufferText.get(), bufferText.get() + bufferLen });

Alternatively, define your own exception type:

#include <utility>
#include <exception>
#include <memory>


class my_error : public std::exception
{
    std::unique_ptr<char[]> msg;

public:
    my_error(std::unique_ptr<char[]>&& msg) noexcept
      : msg(std::move(msg))
    {
    }

    const char* what() const noexcept override
    {
        return msg.get();
    }
};

…

int bufferLen = some_func_to_get_buff_len();
auto bufferText = std::unique_ptr<char[]> { new char[bufferLen + 1] };
some_func_to_get_text(bufferText.get(), bufferLen);
throw my_error(std::move(bufferText));

The main advantage of defining your own exception types is that it allows these types of errors to be handled separately. An additional bonus here would be that it also avoids copying the error string. Since exceptions should only happen in exceptional conditions, this shouldn't really be an issue though…

Like most resource allocations in general, this case can be handled by using a container. The standard container for a string is std::string :

// add + 1 to bufferLen if using older standard than C++17
std::string bufferText(bufferLen);

When the string is destroyed, it will be deallocate its internal buffer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM