1

我不明白为什么这个程序会出现损坏的堆错误(我使用 OpenCV 作为类Mat):

class A {
    private:
    Mat image;      

    static UINT ThreadProc( LPVOID pParam ) {
        A* pThis= (ClientNetwork*)pParam;
        UINT nRet= pThis->DoThreadProc();     // get out of 'static mode'
        return( nRet );
    }
    UINT ClientNetwork::DoThreadProc() {
         vector<uchar> vect;
         while(1) {
             /**** initialize vect and get the image data to decode ****/

             decode(vect);
         }
    }

    public:
    void decode(const vector<uchar>& vectorData){image=imdecode(vectorData, CV_LOAD_IMAGE_COLOR);}
    Mat get_image(){return image;}
    void start() {m_pcThread= AfxBeginThread(ThreadProc, this );}
}

int main() {
    A* a = new A();
    a->start();
    while(1) {
        Mat image = a->get_image();
    }
    delete a;
    return 0;
}

似乎错误来自Mat image = a->get_image();因为如果我返回引用而不是对象的副本,则不再有错误:

Mat* get_image(){return &image;}

Mat* image = a->get_image();

我读到返回一个对象的副本在 C++ 中比引用更优雅。所以我想知道什么是错的。

编辑:Visual Studio 中断,a->decode(vect)但它仅在我返回对象而不是引用时发生。

编辑 2:我编辑了代码以反映完整的程序。我认为问题来自a同时复制和修改的共享对象。我将使用互斥锁查看问题是否仍然存在。

4

3 回答 3

2

a无需初始化即可使用。

int main() {
    A* a;
    vector<uchar> vect;
    while(1) {
        // get the vector of data
        a->decode(vect);

欢迎来到未定义的行为,人群:你。

初始化a以获得更好的结果。

于 2013-03-11T04:09:41.983 回答
2

那就是你自己建议的线程同步问题。图像在无限循环中不断填充。在它中间的某个地方,你试图复制它。灾难的食谱。在每次迭代中,您需要在 DoThreadProc 中的该循环内获取写锁。然后你需要在你的 get_image 中获取一个读锁。您需要使用不会饿死读者的读/写锁库。

或者,您可以使用互斥锁/关键部分。写入循环和读取(get_image)都只是在他们工作时获得对图像的独占访问权。

不过我很好奇-您的线程过程正在无限循环中解码事物。你想在那里做什么?在阅读您期望的图像时?循环迭代中那个时间点的任何图像?

于 2013-03-11T06:00:39.733 回答
1

的复制构造函数cv::Mat不会创建图像的深层副本。它只是创建对原始的引用Mat并增加其引用计数。在该类的以下函数中,该return语句调用复制构造函数,返回对原始 的引用image,这可能是堆损坏的原因:

Mat get_image(){ return image; }

您应该返回如下的深层副本image,以免image意外修改原始内容。

Mat get_image(){ return image.clone(); }
于 2013-03-12T05:17:52.483 回答