我准备并行化一些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
成员函数中不可访问?
啊,我忘记了一切都通过C++的价值传递,除非明确指定。谢谢。 – misha 2013-04-09 06:55:26