5

考虑以下代码示例。为什么下面标记的行会在运行时触发断点/异常?

int main() {
    Mat m1 = Mat::zeros(10, 1, CV_32FC1);
    Mat m2 = Mat::zeros(10, 3, CV_32FC1);

    vector<float> v1(m1); // works
    Mat m2sub = m2.col(0);
    Mat m2subClone = m2.col(0).clone();
    vector<float> v2(m2subClone); // works
    vector<float> v3(m2sub); // doesn't work
return 0;
}

这似乎很奇怪,因为在 mat.hpp 中被称为:

template<typename _Tp> inline Mat::operator std::vector<_Tp>() const {
    std::vector<_Tp> v;
    copyTo(v);
    return v; // <- breaks here
}

和 copyTo 似乎 memcpy 数据。

它没有给出错误消息,但我在堆栈跟踪中看到它在 return 语句处中断,然后深入到“operator new”和“ntdll.dll!RtlpAllocateHeap()”的某个地方。

奇怪的是,在我的完整代码中,它在一个稍微不同的地方中断:在 memcpy 的 copyTo(v) 内,并抛出“访问冲突写入位置 0x0000000001F43D4C。”。我的完整代码看起来与上面的完全一样,但矩阵更大。

编辑:如果在上面的示例中,我将矩阵更改为

    Mat m1 = Mat::zeros(5900, 1, CV_32FC1);
    Mat m2 = Mat::zeros(5900, 3, CV_32FC1);

该片段在与我的完整代码相同的位置失败,并出现访问冲突错误。

我有超过 2GB 的可用 RAM,并且该应用程序被编译为 64 位应用程序,因此它不应该是“内存不足”问题(?)

4

1 回答 1

2

我不太了解 OpenCV Mat 类,但我猜矩阵中的列有一些共享的东西,所以记忆它可能不是一个好主意。检查 Mat::row 方法的 OpenCV 文档(这里, Mat::col 方法具有关于“共享标头”的相同参数),有一条说明表明以下不是一个好主意

Mat A;
...
A.row(i) = A.row(j); // will not work

并且您应该使用以下内容:

A.row(j).copyTo(A.row(i));

所以,也许在你的代码中你应该使用这个:

vector<float> v3;
m2sub.copyTo(v3);
于 2013-10-25T19:54:46.047 回答