这是我第一次在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) ()
我不知道哪里出了问题。指针cost
是否会导致这种情况?
答案 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循环的依赖是可疑的,至少应该更好地重构。但这些东西对于解决问题并不那么重要。
至少使用这个新代码,现在应该可以轻松识别出现问题的区域。