【问题标题】:Segmentation fault but array object is not going out of bounds (C++)分段错误,但数组对象没有超出范围(C++)
【发布时间】:2016-11-12 17:50:54
【问题描述】:

还有其他关于分段错误的常见原因的帖子,但我认为我在这里创建的内置数组对象 (result) 在我为其赋值时不会超出范围。
我认为这可能对未来数组未超出范围的人有所帮助,而且我也没有看到很多关于制作 2D 内置数组对象的东西——我见过的例子几乎完全是向量或 std :array 对象。

这里是可运行的,相关代码:

ma​​trix.h

#ifndef MATRIX_H
#define MATRIX_H

#include <initializer_list>
using std::initializer_list;

typedef unsigned int uint;

class Matrix {

  public:

    Matrix(uint rows, uint cols);  
    ~Matrix();  
    Matrix add(double s) const;  
    const uint numRows() const;  
    const uint numCols() const;  
    double & at(uint row, uint col);  
    const double & at(uint row, uint col) const;  

  private:

    uint rows, cols;
    double ** matrix;

    void makeArray() {
      matrix = new double * [rows];
      for(uint i = 0; i < rows; ++i) {
        matrix[i] = new double [cols];
      }
    }

};

#endif  

ma​​trix.cpp

#include "matrix.h"
Matrix::Matrix(uint rows, uint cols) {
  //Make matrix of desired size
  this->rows = rows;
  this->cols = cols;

  makeArray();

  //Initialize all elements to 0
  for(uint i = 0; i < rows; ++i) {
    for(uint j = 0; j < cols; ++j) {
      this->matrix[i][j] = 0.0;
    }
  }
}
Matrix::~Matrix() {
  for(uint i = 0; i < numRows(); ++i) {
    delete[] matrix[i];
  }
  delete[] matrix;
}
const uint Matrix::numRows() const {
  return this->rows;
}

const uint Matrix::numCols() const {
  return this->cols;
}

double & Matrix::at(uint row, uint col) {
  return matrix[row][col];
}

const double & Matrix::at(uint row, uint col) const {
  return matrix[row][col];
}

Matrix Matrix::add(double s) const {
  uint r = this->numRows();
  uint c = this->numCols();

  Matrix * result;
  result = new Matrix(r, c);

  for(uint i = 0; i < r; ++i) {
    for(uint j = 0; j < c; ++j) {
      result->at(i,j) = (this->at(i,j)) + s;
    }
  }

  return * result;
}  

ma​​in.cpp

#include <iostream>
#include <cstdlib>
#include "matrix.h"

using namespace std;

typedef unsigned int uint;

int main() {

  Matrix * matrix;
  matrix = new Matrix(3, 2); //Works fine

  double scaler = 5;

  matrix->at(2,1) = 5.0; //Works fine

  Matrix r = matrix->add(scaler); //DOESN'T WORK

  return EXIT_SUCCESS;
}  

知道为什么add 函数会导致分段错误吗?我用来填充结果 Matrix 对象的 for 循环没有超出范围,而且我对 C++ 不够熟悉,不知道还有什么可能导致它。
提前致谢。

【问题讨论】:

  • 可能还有其他问题。不要尝试自己管理动态内存分配,除非您绝对确定需要。
  • 我们是否应该忽略add() 成员中的内存泄漏,而只关注一个更大的问题,即What is the Rule of 3
  • Matrix * result; [...] return * result; 你为什么要这样做?顺便说一句,我认为您的代码中没有任何充分的理由使用单个 *
  • 与错误无关,但一般建议:由于您不想表示锯齿状矩阵,并且尺寸在构造时是固定的,因此将数据存储在一个单独的连续中可能会更好大批。您可以使用std::vector&lt;double&gt; 作为数据存储进一步简化代码。
  • @Mazzone -- 您在add 函数中按值返回Matrix,并且您未能实现用户定义的复制构造函数或赋值运算符。你甚至没有这些函数的存根,表明你知道它们。你说你必须这样写东西,但你没有告诉过这些基本的东西,比如“3规则”吗?为什么你被告知以某种方式做事,而你却没有被告知完成目标所需的所有准备工作?

标签: c++ arrays oop multidimensional-array segmentation-fault


【解决方案1】:

问题是缺少手动定义的复制构造函数或赋值运算符,因为该类管理资源(内存)。

如果分配了类的实例,或用于创建副本,则结果将是引用相同内存的两个不同对象。当这两个引用同一内存的对象被销毁时,内存被释放两次。其结果是未定义的行为。

查找“三法则”以获得解决方案。在 C++11 中,这通常成为“五规则”或“零规则”(这涉及到使用技术首先避免该问题)。

add() 函数还有一个非常重要的问题,因为它会动态创建一个Matrix,然后返回它的副本。即使解决了复制对象的问题,这也会导致内存泄漏。该函数实际上看起来像是用垃圾收集语言编写的东西 - 问题是 C++ 不是垃圾收集。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-13
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    • 1970-01-01
    相关资源
    最近更新 更多