2013-04-09 45 views
2

我準備並行化一些C++ OpenCV代碼。我遇到了段錯誤,我無法理解發生了什麼。爲什麼這個OpenCV代碼段錯誤?

下面是代碼:

class ExhaustiveComparisonMT 
{ 
    vector<Mat> *m_sigs; 
    Mat *m_dist; 
public: 
    ExhaustiveComparisonMT(vector<Mat> sigs, Mat dist) 
    { 
     m_sigs = &sigs; 
     m_dist = &dist; // gdb breakpoint 1 here 
    } 

    void operator() (size_t last_row, size_t last_col) const 
    { 
     Mat diff = (*m_sigs)[0].clone(); // segfault happens here, gdb breakpoint 2 here 
     for (size_t i = 0; i != last_row; ++i) 
     for (size_t j = 0; j != last_row; ++j) 
     { 
      cv::absdiff((*m_sigs)[i], (*m_sigs)[j], diff); 
      m_dist->at<double>(i, j) = cv::sum(diff).val[0]; 
     } 
    } 
}; 

void 
exhaustive_comparison(vector<Mat> sigs, Mat dist) 
{ 
    size_t width = sigs.size(); 
    ExhaustiveComparisonMT ecmt(sigs, dist); 
    ecmt(width, width); 
} 

基本上,矩陣的矢量被傳遞給構造。指向矢量的指針保存爲成員變量,因此可以在exhaustive_comparison中再次訪問該矢量。但是,該函數試圖訪問向量的第一個元素。

我試着用兩個斷點(見代碼)來診斷gdb的問題。在斷點1上:

(gdb) p (*m_sigs)[0] 
$1 = (cv::Mat &) @0x7fffee77d010: {flags = 1124024325, dims = 2, rows = 1, cols = 712, data = 0x624ec0 "", refcount = 0x0, datastart = 0x624ec0 "", dataend = 0x6259e0 "", 
    datalimit = 0x6259e0 "", allocator = 0x0, size = {p = 0x7fffee77d018}, step = {p = 0x7fffee77d060, buf = {2848, 4}}} 

因此,正確訪問第一個元素。現在,我們進入斷點2並嘗試相同的操作:

(gdb) p (*m_sigs)[0] 
$2 = (cv::Mat &) @0x7fffee77d010: <error reading variable> 

第一個元素似乎不再可訪問!它的地址是相同的(0x7fffee77d010)。這裏發生了什麼?

最後,如果我向前一步,我得到:

Program received signal SIGSEGV, Segmentation fault. 
0x00007ffff7a0dd50 in cv::Mat::copyTo(cv::_OutputArray const&) const() from /usr/local/lib/libopencv_core.so.2.4 

OpenCV的嘗試訪問的第一個元素克隆它,失敗。

爲什麼第一個元素在構造函數中可訪問,但在exhaustive_comparison成員函數中不可訪問?

回答

5
ExhaustiveComparisonMT(vector<Mat> sigs, Mat dist) 
{ 
     m_sigs = &sigs; 
     m_dist = &dist; // gdb breakpoint 1 here 
} 

您是通過複製傳遞的變量sigsdist - 這意味着,它們的壽命是有限的這一功能。

如果您嘗試獲取地址並在之後使用它,您將指向未知數據 - 因爲在離開此函數後,這些對象將被銷燬並且其地址將用於其他事情。

如果你想把你作爲參數傳遞的對象的地址,你應該使用引用 - 這樣,你將實際檢索原始對象的地址。當然,這會工作,假設你將函數傳遞給函數,並且在此期間不會被銷燬。

ExhaustiveComparisonMT(vector<Mat> &sigs, Mat &dist) 
{ 
     m_sigs = &sigs; 
     m_dist = &dist; // gdb breakpoint 1 here 
} 
+0

啊,我忘記了一切都通過C++的價值傳遞,除非明確指定。謝謝。 – misha 2013-04-09 06:55:26