用指针调用函数会导致段错误

时间:2017-03-23 16:05:28

标签: c++ segmentation-fault

这是我第一次在StackOverflow上发布问题。我正在编写一段C ++代码,试图解决半全局匹配问题。但是我在这个段故障问题上陷入困境已经两天了。

我有3个文件:main.cpp,sgm.cpp,sgm.h。在main.cpp中,我将为后面的两个3D矩阵创建空间。

  unsigned short ***cost = new unsigned short**[leftImg.rows]; // cost matrix W*H*D
  unsigned short ***aggreg = new unsigned short**[rightImg.rows]; // aggregated cost W*H*D
  for(int row=0; row<leftImg.rows; row++) {
    cost[row] = new unsigned short*[leftImg.cols];
    aggreg[row] = new unsigned short*[rightImg.cols];
    for(int col=0; col<leftImg.cols; col++) {
      cost[row][col] = new unsigned short[disparityRange]();
      // fill_n(cost[row][col], disparityRange, 0);
      aggreg[row][col] = new unsigned short[disparityRange]();
    }
  }

然后在sgm.cpp中,我实现了一个函数:

  void calculatePixelCost(unsigned short ***cost, cv::Mat& leftImg, cv::Mat& rightImg, int dRange) {
    for(int i=0; i<leftImg.rows; i++)
      for(int j=0; j<rightImg.cols; j++)
        for(int d=0; d<dRange; d++) {
       cost[i][j][d]=calculatePixelBT(leftImg, rightImg, i, j, d);
    }     
  }

当我通过写:

从main.cpp调用此函数时
sgm::calculatePixelCost(cost, leftImg, rightImg, disparityRange);

该程序在调用时崩溃了。 Bellow是错误信息:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000401ef9 in sgm::calculatePixelCost(unsigned short***, cv::Mat&, cv::Mat&, int) ()

enter image description here

我不知道哪里出了问题。指针cost是否会导致这种情况?

1 个答案:

答案 0 :(得分:1)

让我们打破这一点。

首先,您构建的矩阵类型通常被称为“矩形矩阵”,其中

  • 所有行的长度相同
  • 所有列的长度相同
  • 所有楼层都有相同的长度

这意味着没有理由在此级别使用指针间接。

所以我们的第一个重构:

unsigned short *cost = new short[leftImg.rows * leftImg.cols * disparityRange]{};
unsigned short *aggreg = new short[rightImg.rows * rightImg.cols * disparityRange]{};

//All of this is now irrelevant and unnecessary.
//for(int row=0; row<leftImg.rows; row++) {
    //cost[row] = new unsigned short*[leftImg.cols];
    //aggreg[row] = new unsigned short*[rightImg.cols];
    //for(int col=0; col<leftImg.cols; col++) {
        //cost[row][col] = new unsigned short[disparityRange]();
        // fill_n(cost[row][col], disparityRange, 0);
        //aggreg[row][col] = new unsigned short[disparityRange]();
    //}
//}

您需要一个可以帮助您访问正确索引的函数:

size_t get_index(size_t i, size_t j, size_t k, size_t rows, size_t cols, size_t floors) {
    return i * cols * floors + j * floors + k;
}

所以在calculatePixelCost中,编写这样的代码:

void calculatePixelCost(unsigned short *cost, cv::Mat& leftImg, cv::Mat& rightImg, int dRange) {
    for(int i=0; i<leftImg.rows; i++)
        for(int j=0; j<rightImg.cols; j++)
            for(int d=0; d<dRange; d++) {
                cost[get_index(i, j, d, leftImg.rows, leftImg.cols, dRange)] = calculatePixelBT(leftImg, rightImg, i, j, d);
            }     
}

此代码可帮助您缩小问题范围。但我们可以做得更好。

看,你不应该把你的指针全部裸露出来并像这样曝光。孩子们可能正在查看你的代码!

因为我们处于C ++领域,处理这种情况的正确方法是在一个类中包装。既然你需要一个合适的“3-dim矩阵”对象,那么让我们做一个合适的矩阵类。

class matrix {
    size_t _rows, _columns, _floors;
    //We'll use a std::vector object so that we no longer see any naked pointers.
    std::vector<short> values;
public:
    matrix(size_t rows, size_t columns, size_t floors) :
        _rows(rows), _columns(columns), _floors(floors),
        values(_rows * _columns * _floors)
    {}

    short & operator()(size_t row, size_t column, size_t floor) {
        if(row >= _rows || column >= _columns || floor >= _floors)
            throw std::runtime_error("Invalid access to matrix!");
        return values[row * _columns * _floors + column * _floors + floor];
    }

    short const& operator()(size_t row, size_t column, size_t floor) const {
        if(row >= _rows || column >= _columns || floor >= _floors)
            throw std::runtime_error("Invalid access to matrix!");
        return values[row * _columns * _floors + column * _floors + floor];
    }

    //We will not implement a resize function, as the logic of how it should work
    //hasn't been established. It's probably better to simply allow new matrices
    //to overwrite this one using the default-defined copy and move constructors.
    //void resize(size_t rows, size_t columns, size_t floors);

    bool operator==(matrix const& m) const {
        if(!(_rows == m._rows && _columns == m._columns && _floors == m._floors)) return false; 
        return values == m.values;
    }

    size_t rows() const {return _rows;}
    size_t columns() const {return _columns;}
    size_t floors() const {return _floors;}
};

然后在代码中使用此矩阵:

matrix cost{leftImg.rows, leftImg.cols, disparityRange};
matrix aggreg{rightImg.rows, rightImg.cols, disparityRange};

以及:

void calculatePixelCost(matrix & cost, cv::Mat& leftImg, cv::Mat& rightImg, int dRange) {
    for(int i=0; i<leftImg.rows; i++)
        for(int j=0; j<rightImg.cols; j++)
            for(int d=0; d<dRange; d++) {
                cost(i, j, d) = calculatePixelBT(leftImg, rightImg, i, j, d);
            }     
}

看看要了解多少简单?是的,它预先做的更多,但你可以更容易地推断代码正在做什么以及为什么需要这样做。

还有很多东西需要检查。例如,您对三重嵌套for循环的依赖是可疑的,至少应该更好地重构。但这些东西对于解决问题并不那么重要。

至少使用这个新代码,现在应该可以轻松识别出现问题的区域。