首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用新运算符和2D数组防止内存分配失败的正确方法

使用新运算符和2D数组防止内存分配失败的正确方法
EN

Stack Overflow用户
提问于 2012-03-27 19:13:54
回答 4查看 662关注 0票数 1

在下面的代码中,是创建2D数组时需要的初始第一个循环,或者如果内存分配失败,指向实际行的指针会被初始化为NULL吗?

代码语言:javascript
复制
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");
}

更新

为了澄清,我看的代码是:

代码语言:javascript
复制
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   }
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-03-27 19:43:25

此操作未初始化使用new unsigned char*[height]分配的数组。如果任何分配失败,它将引发异常。在代码中,您接下来将初始化数组。我觉得这个应该是这样的:

代码语言:javascript
复制
std::fill_n(row_pointers, height, 0);

当然,如果任何后续分配失败,该数组将被泄露,所有其他分配到目前为止的数组也是如此。你可以在catch-block中清理这个烂摊子。

就我个人而言,我无法应付多次的清理:这是太复杂了,无法理顺。就我个人而言,我会使用两个std::vector<T>来代替,打包成一个类:

  • 一个std::vector<unsigned char*>,它被初始化为指向子向量的开始
  • 一个包含所有子向量的std::vector<unsigned char>

一旦这些被分配,在第一向量中的指针被设置为在适当的位置指向第二向量。方便的是,如果出了什么问题,两个向量的析构函数将负责清理。

如下所示:

代码语言:javascript
复制
#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函数的指针。

票数 3
EN

Stack Overflow用户

发布于 2012-03-27 19:33:46

这取决于编译器和选项,但为了安全起见,您应该保持初始化,如果您希望它。

一些带有debug选项的编译器将用0值初始化row_pointers数组。其他人会用标记来填充它(比如0xcc),而其他人只会让它没有初始化。

我不确定,但我认为也可能有一些选项将返回NULL,而不是抛出std::bad_alloc,在这种情况下,额外的初始化将是不必要的。

然而,当有疑问的时候,要明确!

票数 1
EN

Stack Overflow用户

发布于 2012-03-27 19:42:28

这对你来说可能是个很好的读物:

http://www.cplusplus.com/reference/std/new/operator%20new/

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9896088

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档