【问题标题】:Possible dynamic allocation issues可能的动态分配问题
【发布时间】:2020-09-20 00:13:50
【问题描述】:

现在我正试图让我的代码(简单的 POD 容器)尽可能稳定地运行。我主要关心的是内存分配和释放(new[] 和 delete[] 运算符)。是否有可能从中得到任何不受欢迎的行为(如 SIGSEGV 或异常)? 这是我写的一个小测试示例:

class my_vector{
    private:
        long* _data;
        size_t _size;
        size_t _capacity;
    public:
        my_vector()
       {
           this->_data = new long[10];
           this->_size = 0;
           this->_capacity = 10;
       };

        ~my_vector()
       {
           delete[] this->_data;
       };

        void add(long value)
       {
           if (this->_size == this->_capacity)
                 this->expand();
           this->_data[this->_size] = value;
           this->_size++;
       };
    private:
        void expand()
        {
           long* tmp = new long[this->_capacity*2];
           memcpy(tmp, this->_data, sizeof(long)*this->_size);
           this->_capacity *= 2;
           delete[] this->_data;
           this->_data = tmp;
        };
}

【问题讨论】:

  • 如果您检查分配是否成功,并且不删除不属于您的数据,您应该没有问题。当您在这里分配时:this->_data = new long[10]; 您不会检查分配是否成功。而且,如果你从这个类中复制任何对象,你会遇到一些严重的问题。我建议您: 1. 检查分配是否成功,以及 2. 关注The rule of three/five/zero。如果你两者都做,你应该没有任何问题。看看智能指针,这可能会有所帮助
  • @Pablochaches - this->_data = new long [10] 如果失败会抛出异常。这不需要检查(尽管异常最终需要被捕获,否则程序将终止)。

标签: c++ exception memory-management segmentation-fault new-operator


【解决方案1】:

默认情况下,new[] 表达式如果失败(例如,如果动态内存分配失败)会引发异常。

如果正在构造的任何对象的构造函数因抛出异常而失败,则new [] 表达式将具有抛出该异常的(净)效果。在最终发出异常之前还会发生一些其他事情 - 例如,如果在动态分配的数组中构造第三个对象失败,则将调用先前构造的两个对象的析构函数。就调用代码而言,如果发出异常,则new[] 表达式创建的对象都不存在。这是标准中规定的。

如果抛出异常但从未被捕获,则程序将终止。这是正常的,也是意料之中的。

delete [] 表达式通常不会抛出,除非被销毁对象的析构函数抛出。定义一个抛出异常的析构函数通常被认为是非常糟糕的做法,因此应该避免。

new 表达式的 nothrow 形式本身不会引发异常。在这种情况下,new 表达式会在失败时给出一个空指针。

new[]delete [] 表达式本身不会导致SIGSEGV 或任何其他形式的异常终止。如果发生这种情况,则表明某些 other 代码表现出未定义的行为(例如,写在数组末尾之后)。这可以在数组中对象的构造函数或析构函数中,也可以在其他代码中。

【讨论】:

    猜你喜欢
    • 2021-06-05
    • 2012-12-22
    • 2011-01-19
    • 2022-01-22
    • 2022-01-17
    • 2022-01-10
    • 2017-05-07
    • 2011-11-15
    相关资源
    最近更新 更多