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) からポインター値をコピーし、それを呼び出した関数から渡されたポインター値を上書きしようとしているようです (つまり、" img" MyFrame::changeWP 内の変数)。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 オブジェクトを持つことができ、それらの間で相互排除はありません。繰り返しますが、ウィンドウは 1 つしかないため、これはおそらく実際の問題ではありませんが、それでも...

おそらく他にもありますが、最初はこれで十分です。

于 2011-03-05T03:36:45.370 に答える