Как безопасно высвободить ресурсы, выделенные конструктором? - PullRequest
1 голос
/ 26 марта 2019

Я использую функцию C, которая должна записывать текст в буфер, расположенный в конструкторе.Проблема в том, что мне нужно передать строку в конструктор исключений, но после создания исключения память, выделенная для текста, теряется:

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
            //???
        }
    }
};

Теперь текст где-то теряется.Подскажите пожалуйста, как решить эту проблему.

Ответы [ 2 ]

0 голосов
/ 26 марта 2019

Как и большинство распределений ресурсов в целом, этот случай может быть обработан с использованием контейнера. Стандартный контейнер для строки - std::string:

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

Когда строка уничтожена, она освобождает свой внутренний буфер.

0 голосов
/ 26 марта 2019

Я предполагаю runtime_error в вашем коде выше относится к std::runtime_error? В этом случае вы можете просто передать ему std::string и освободить буфер. Например

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 });

В качестве альтернативы, определите свой собственный тип исключения:

#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));

Основным преимуществом определения ваших собственных типов исключений является то, что они позволяют обрабатывать ошибки такого типа отдельно. Дополнительным бонусом здесь будет то, что он также избегает копирования строки ошибки. Поскольку исключения должны происходить только в исключительных условиях, это не должно быть проблемой, хотя…

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...