#c #oop
#c #ооп
Вопрос:
Я использую функцию 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
//???
}
}
};
Теперь текст где-то потерян. Пожалуйста, скажите мне, как решить эту проблему.
Комментарии:
1. Это не «где-то потеряно». Это в объекте exception. Он должен быть освобожден в своем деструкторе, как и любой другой ресурс, приобретенный в конструкторе.
2. @user207421 однако вам придется написать дополнительный код, чтобы освободить буфер. А если пользователь класса не знает, как его освободить?
3. Есть ли возможность использовать
std::string
вместо этого?4. @vahancho Какую конструкцию нужно написать, чтобы std :: string мог работать с этой функцией C, которая работает с указателями char?
Ответ №1:
Я предполагаю, что 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[]>amp;amp; 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));
Основное преимущество определения собственных типов исключений заключается в том, что это позволяет обрабатывать эти типы ошибок отдельно. Дополнительным бонусом здесь было бы то, что это также позволяет избежать копирования строки ошибки. Поскольку исключения должны происходить только в исключительных условиях, на самом деле это не должно быть проблемой…
Ответ №2:
Как и в большинстве распределений ресурсов в целом, этот случай может быть обработан с помощью контейнера. Стандартным контейнером для строки является std::string
:
// add 1 to bufferLen if using older standard than C 17
std::string bufferText(bufferLen);
Когда строка будет уничтожена, она освободит свой внутренний буфер.
Комментарии:
1. Спасибо. если я передам указатель на строку символов в конструкторе std :: string , освободит ли это память в деструкторе?
2. @sddvxd нет. Строка копирует только содержимое указанной строки. Он не присваивает права собственности на указатель.