1

我有一个类,我试图将它的一些成员函数转换为在不同的线程中运行。虽然程序没有问题,但它在尝试从图像缓冲区(由不同的线程更新)读取时崩溃。似乎问题是由 _beginthread 中的参数传递错误引起的。

下面的代码片段应该更清楚地解释我想要做什么。基本上我想要完成的是让成员函数“fillBuffer”填充图像缓冲区,而其余程序正在做其他事情,包括同时读取相同的图像缓冲区。

非常感谢任何有关语法的帮助。

 const int MaxImgBufferSize = 5;
        class MyFrame : public wxFrame
        {
        public:
            // constructors
            MyFrame(const wxString& title);   

        private:
            static vector <IplImage*> ImgBuffer;
            void  changeWP(wxCommandEvent&);
            void  fillBuffer();
                void  fillBufferFun();
                static void __cdecl getImgFromBuffer(void *);
                static void __cdecl pushImgBuffer(void *);
        };

    vector<IplImage*> MyFrame::ImgBuffer;

        enter code here

    MyFrame::MyFrame(const wxString& title)
           : wxFrame(...)
    {
       // some stuff here
       InitializeCriticalSection(&Section);
       fillBuffer();

      // some code here calls changeWP(wxCommandEvent&) from time to time
    }

    void MyFrame::fillBuffer()
    {
        while(ImgBuffer.size() <= MaxImgBufferSize)
        {
            fillBufferFun();
        }
    }

void MyFrame::fillBufferFun()
{
   ImgBuffer* img;
   // do something with img
   _beginthread(pushImgBuffer, 0, img);
}

void MyFrame::pushImgBuffer(void *p)
{
    EnterCriticalSection(&Section);
    ImgBuffer.push_back( (IplImage*) p );
    LeaveCriticalSection(&Section);
}

static unsigned int __stdcall getImgFromBuffer(void *);

void MyFrame::changeWP(wxCommandEvent&)
{
    // do someting

    IplImage* img = NULL;// new IplImage;
        _beginthreadex( NULL, 0, MyFrame::getImgFromBuffer, img, 0, NULL );

        // do something with img
        fillBuffer();
}

unsigned int MyFrame::getImgFromBuffer(void *p)
{
    EnterCriticalSection(&Section);
    p = (void *)ImgBuffer[0];
    ImgBuffer.erase(ImgBuffer.begin());
    LeaveCriticalSection(&Section);
    return 0;
}
4

1 回答 1

1

这里有几个问题:

  1. 您的代码正在崩溃,因为您的 getImgFromBuffer 函数没有您想要的效果。看来,从 getImgFromBuffer 的主体来看,您正试图从向量 (MyFrame::ImgBuffer) 中复制一个指针值,并使用它覆盖从调用它的函数传入的指针值(即“ myFrame::changeWP 中的 img" 变量)。我说“似乎”是因为您在调用 getImgFromBuffer 之前初始化了 MyFrame::changeWP (IplImage* img = new IplImage) 中的“img”变量 - 为什么在分配另一个不同的指针之前将新对象分配给指针指向它的指针值(当然,导致内存泄漏)?无论如何,赋值目前只是覆盖了“p”的值 getImgFromBuffer 函数内部的参数,按值传递,函数退出时会丢失。如果您希望 getImgFromBuffer 覆盖从其调用者传入的指针变量,那么您需要通过指向指针变量的指针,如下所示:
void MyFrame::changeWP(wxCommandEvent&)
{
    IplImage* img = NULL;  // No memory leak, this time.
    _beginthread(MyFrame::getImgFromBuffer, 0, & img);
    //...
}

void MyFrame::getImgFromBuffer(void ** p)
{
    //...
    *p = (void *)ImgBuffer[0];
    //...
}
  1. 我看不出“部分”是如何定义的,但无论是静态的还是实例的,无论哪种方式,它至少都是不好的形式。如果它是静态的,那么您就犯了一个错误,即每次构建时都重新初始化它。我意识到这是一个代表顶级窗口的类,所以你可能不会制作超过一个,但它仍然是一种糟糕的形式。如果 Section 是一个实例变量,那么您可能有多个 Section 对象试图保护单个(静态)资源,它们之间没有互斥。同样,只有一个窗口,所以这可能不是你的实际问题,但仍然......

可能还有更多,但这已经足够开始了。

于 2011-03-05T03:36:45.370 回答