简体   繁体   中英

Why does this OpenCV code segfault?

I'm preparing to parallelize some of my C++ OpenCV code. I've come across a segfault, and I can't understand what's happening.

Here is the code:

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

Basically, an vector of matrices is being passed to the constructor. A pointer to the vector is kept as a member variable, so the vector can be accessed again in exhaustive_comparison . However, that function trips up trying to access the first element of the vector.

I've tried to diagnose the problem with gdb by putting two breakpoints (see code). At breakpoint 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}}}

Therefore, the first element is being accessed correctly. Now, we go to breakpoint 2 and try the same thing:

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

The first element appears to be no longer accessible! Its address is the same (0x7fffee77d010). What's going on here?

Finally, if I step forward, I get:

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 tries to access the first element to clone it, and fails.

Why is the first element accessible in the constructor, but not accessible in the exhaustive_comparison member function?

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

You are passing your variables sigs and dist by copy - meaning, their lifetime is limited to this function.

If you try to get their address and use it afterwards, you are going to point to unknown data - because upon leaving this function, these objects will be destroyed and their addresses will be used for something else later on.

If you want to have the address of the objects you passed as parameters, you should use references - that way, you will actually retrieve the address of the original objects. This will work assuming, of course, you're passing lvalues to your functions and they are not destroyed in the meantime.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM