Массив, выделенный с new unsigned char*[height]
, не инициализируется этой операцией. Если какое-либо распределение завершится неудачно, оно выдаст исключение. В вашем коде вы затем инициализируете свой массив. Я думаю, это должно выглядеть так:
std::fill_n(row_pointers, height, 0);
Конечно, если какое-либо последующее распределение завершится неудачно, этот массив будет просочиться, как и все остальные массивы, выделенные до сих пор. Вы можете убрать этот беспорядок в catch
-блоке.
Лично я не могу справиться с несколькими очистками: это слишком сложно сделать правильно. Лично я бы вместо этого использовал два std::vector<T>
, связанных в класс:
- one
std::vector<unsigned char*>
, который инициализируется, чтобы указывать на начало субвекторов
- один
std::vector<unsigned char>
для хранения всех подвекторов
Как только они распределены, указатели в первом векторе устанавливаются так, чтобы указывать на второй вектор в соответствующих местах. Удобно, если что-то пойдет не так, деструкторы двух векторов позаботятся об очистке.
Вот как это будет выглядеть:
#include <vector>
#include <cstddef>
struct array2d
{
array2d(std::size_t height, std::size_t width)
: inner_(height * width)
, outer_(height)
{
for (std::size_t i(0); i != height; ++i) {
this->outer_[i] = &this->inner_[i * width];
}
}
unsigned char** get() { return &this->outer_[0]; }
std::vector<unsigned char> inner_;
std::vector<unsigned char*> outer_;
};
Когда вы получили объект picture
этого типа, вы можете использовать picture.get()
, чтобы получить указатель, подходящий для передачи в функции C.