【问题标题】:Segmentation fault when creating a row-major array创建行优先数组时出现分段错误
【发布时间】:2015-10-02 15:28:48
【问题描述】:

我正在尝试实现一个以行为主的数组,它基本上是二维数组的一维表示。

这是我的类定义

class RMA{
    public:

    RMA(){
        size_=0;
        row_=0;
        column_=0;
        arr_ = new double[size_];
    }

    RMA(int n, int m){
        size_ = n*m;
        column_ = m;
        row_ = n;
        if(size_== 0) arr_ = 0;
            else arr_ = new double[size_];
    }

    RMA(const RMA& arr) {
        size_ = arr.size_;
        if(this != &arr){
            delete [] arr_;
            arr_ = new double[size_];
            for(int i=0; i<size_; i++){
                arr_[i] = arr.arr_[i];
            }
        }
        return *this;
    }

    const double& operator() (int n, int m) const{
        return arr_[n*column_+m];
    }

    double& operator()(int n, int m){
        return arr_[n*column_+m];
    }  
    ~RMA(){delete[] arr_ ;}

    private:
        int size_;
        int column_;
        int row_;
        double* arr_;
}

我有一个创建数组的调用函数。

RMA create_array() {
    RMA arr;
    arr = RMA(N, M);
    std::cout<<"success";
    return arr;
}

这是我的客户

int main(int argc, char* argv[]) {

    RMA arr = create_array();
    return 0;
} 

我最终得到分段错误。我做错了什么。

【问题讨论】:

  • 故障出现在哪里?当它发生时,你试图做什么?
  • arr_ = new double[size_]; size_ 有多大?而且您的代码至少违反了Rule of Three multiple 次的一部分。
  • 调用create_array()时出现故障
  • 大小200万左右
  • 你违反了rule of three

标签: c++ arrays segmentation-fault


【解决方案1】:

您使用操作,而不是克隆数组,而是获取对象的浅表副本,当使用析构函数时,它们会尝试释放相同的内存块。

实现以下操作:

RMA::RMA(const RMA&); // copy constructor - clone buffer
RMA& operator=(const &RMA); // assignment - clone buffer, release old

也代替:

 RMA rma;
 rma = RMA(a,b);

用途:

 RMA rma = RMA(a,b) or RMA rma(a,b);

编辑:构造函数代码:

RMA::RMA(const RMA &rma) : size_(0), row_(0), column_(0), buffer_(0)
{
   *this = rma;
}

RMA &operator=(const RMA&rma)
{
   double *old = buffer_;
   size_ = rma.size_;
   row_ = rma.row_;
   column_ = rma.column_;
   buffer_ = new double[size_];
   memcpy(buffer_, rma.buffer_, sizeof(buffer_[0]) * size_);
   delete []old;
   return *this;
}

【讨论】:

  • 添加了复制构造函数,但现在我收到了从构造函数返回值的错误 return *this;
  • @Antithesis 构造函数不应返回值。
  • 我是否需要在我的私有属性中添加双缓冲_。不知道你为什么添加这个。
  • 那个copy-ctor正好是copy/swap idiom相反,这是首选。如果您要提供一个通过调用另一个关于 copy-ctor 和赋值运算符来定义的方法,那么这与它应该做的完全相反。
  • 你也应该加入 move ctor & assignment operator。
【解决方案2】:

最好的解决方案是去掉所有的new/delete、复制构造函数和绒毛。使用私有成员变量来管理内存,遵循Rule of Zero。像这样:

struct RMA
{
    RMA(size_t r = 0, size_t c = 0)
        : row(r), column(c), arr(r * c) {}

    const double& operator() (int n, int m) const
        { return arr[n * column + m]; }

    double& operator() (int n, int m)
        { return arr[n * column + m]; }

private:
    std::vector<double> arr;
    size_t row, column;
};

就是这样。您不应该编写任何复制构造函数、赋值运算符、移动任何内容,因为默认生成的已经做了正确的事情。

注意。 row 在我的示例中实际上也是多余的,您可以将其删除并在需要时将其计算为 arr.size() / column

您可以在向量上使用.at( ) 而不是[ ],以便为越界访问抛出异常,而不是导致未定义的行为。

【讨论】:

    猜你喜欢
    • 2016-01-07
    • 2011-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-31
    • 1970-01-01
    • 2013-02-23
    相关资源
    最近更新 更多