In the code below is the initial first loop needed when creating a 2D array, or if there is a failed memory allocation will the pointers to the actual rows be initialized to NULL?
unsigned char **row_pointers;
try
{
row_pointers = new unsigned char *[height];
for (int i = 0; i < height; ++i)
row_pointers[i] = NULL;
for (int i = 0; i < height; ++i)
row_pointers[i] = new unsigned char[width];
}
catch (std::bad_alloc)
{
throw std::runtime_error("Failure to allocate memory for raw data");
}
UPDATE
To clarify, the code I am looking at is:
149 /*
150 * Allocate sufficient space for the data
151 */
152 unsigned char **row_pointers;
153 try
154 {
155 row_pointers = new unsigned char *[height]();
156 for (int i = 0; i < height; ++i)
157 row_pointers[i] = new unsigned char[width];
158 }
159 catch (std::bad_alloc)
160 {
161 /*
162 * If insufficient memory than try and clean up
163 * and throw runtime error
164 */
165 for (int i = 0; i < height; ++i)
166 {
167 if (row_pointers[i] != NULL)
168 {
169 delete row_pointers[i];
170 }
171 }
172 throw std::runtime_error("Failure to allocate raw memory for data");
173 }
... // White Space
177
178 /*
179 * Now read the data all at once (no need to handle interlacing
180 */
181 png_read_image(m_pPNG, row_pointers);
182
183 for (int i = 0; i < height; ++i)
184 {
185 for (int j = 0; j < width; ++j)
186 std::cout << row_pointers[i][j];
187 std::cout << std::endl;
188 }
The array allocated with
new unsigned char*[height]is not initialized by this operation. If any allocation fails it will throw an exception. In your code you next initialize you array. I think this should look like this:Of course, if any subsequent allocation fails this array will be leaked as will all the other arrays allocated so far. You could clean this mess up in the
catch-block.Personally, I cannot cope with multiple clean-ups: it is just too complicated to get right. Personally I would use two
std::vector<T>instead, bundled into a class:std::vector<unsigned char*>which gets initialized to point to the start of the subvectorsstd::vector<unsigned char>to hold all of the subvectorsOnce these are allocated, the pointers in the first vector are set up to point into the second vector at appropriate locations. Conveniently, if anything goes wrong the destructors of the two vectors will take care of the clean-up.
Here is how this would look like:
When you got an object
pictureof this type you could usepicture.get()to get pointer suitable to be passed to C functions.