2017-03-23 22 views
0

StackOverflowで質問を投稿するのは初めてです。私は半包括的な問題を解決しようとしているC++コードを書いています。しかし、私は2日間、このseg faultの問題に悩まされました。ポインタを使って関数を呼び出すと、セグメントエラーが発生する

私はmain.cpp、sgm.cpp、sgm.hという3つのファイルを持っています。 main.cppでは、後で使用する2つの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); 

プログラムは右ここにダウンクラッシュしましたそれを呼び出すとき。

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

enter image description here

間違ってどこに行くかわからない。:ベローはエラーメッセージです。ポインタcostはこれを引き起こしていますか?

+2

[mcve]の作成に時間がかかる場合は、問題を自分で解決するか、ここで質問する*良い*質問があります。 –

+6

3スターのプログラマーにならないでください。 1Dベクトルを使用し、それらの1D位置に 'row'、' col'と 'disparity'をマップします。 –

+6

C言語ではなくC言語を使っているなら、あなたの特定の神格を愛するために、手動でメモリを管理する代わりにベクトルを使用してください。 'std :: vector >>'は、推論するのがずっと簡単です。 – cdhowie

答えて

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](); 
    //} 
//} 

calculatePixelCostでそう

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; 
} 

は、この代わりのようなコードを記述します。

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次元マトリックス"オブジェクトが必要なので、適切なマトリックスクラスを作ってみましょう。

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ループへの依存は不審であり、最低限、リファクタリングする方がよいでしょう。しかし、そのことはあなたの問題を解決するためにあまり重要ではありません。

少なくともこの新しいコードでは、問題が発生している領域を簡単に識別できるはずです。

+0

この詳細なお返事ありがとうございます!本当にこのような素晴らしい内訳を感謝します。長い道のり。 – MaidouPP

+0

'calculatePixelCost'の最初のカットでは、' unsigned short *** cost'からカップルの開始を削除する必要があると思います。と*(コスト+ get_index(i、j、d、leftImg.rows、leftImg.cols、dRange)) 'は不必要に複雑です。 '[]'を使ってください。 – user4581301

+0

@ user4581301修正されました。私はそのコードを修正しようと多くの時間を費やしていませんでした。なぜなら、より良い、より適切なOPの解決に取り組んでいたからです。 – Xirema

関連する問題