2013-04-09 86 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