7

私はboost::threadsを初めて使用します。ドキュメントを読みましたが、実際に適用するのに問題があります。おそらくあなたが助けてくれるでしょうか。まず、私は時間をかけて、まだ理解できない2種類の動作を示す自己完結型のコードリストを作成しました...

このプログラムにより、ユーザーは3つの異なるコマンドを発行できます。

  • タスク[名前]
  • 情報
  • 終了する

目的は、タスクが新しいスレッドでいくつかの作業を開始するが、作業の実行中にコマンドプロンプトに戻ることです。ユーザーはinfoコマンドを実行して、完了したタスクと完了していないタスクを見つけることができます。

デュアルコアWin7マシンとVisualStudio2008Expressを使用しています。

問題1>

コマンドtaskp1p2 p3を発行すると、3つのタスクの実行が開始されます。これは、 infoを発行することで確認できます。数秒後に作業が完了しますが、何らかの理由で、1つまたは2つのタスクで完了フラグが常にtrueに設定されるとは限りません。

問題2>

プログラムを終了すると、次のメッセージが表示されます。

Windowsがexample.exeでブレークポイントをトリガーしました。これは、ヒープの破損が原因である可能性があります。これは、example.exeまたはロードされたDLLのバグを示しています。これは、example.exeにフォーカスがあるときにユーザーがF12キーを押したことが原因である可能性もあります。出力ウィンドウには、より多くの診断情報が表示される場合があります。

うまくいけば、あなたはこの振る舞いを再現して助けることができます。

前もって感謝します。アレックス。

    //WARNING: THIS CODE DOES NOT BEHAVE EXACTLY AS INTENDED
#include <iostream>  
#include <string>
#include <sstream>
#include <boost/thread.hpp>  

using namespace std;

class task {
public:
    string mname;
    bool completed;
    void start()
    {
        int a = 0;
        for (int i=0 ; i<10000; i++)
        {
            for (int j=0 ; j<100000; j++)
            {
                a= i*2;
            }
        }
        this->completed = true;
    }
    task(string name)
    {
        mname = name;
        completed = false; 
    }
};

class taskManager{
    public:
        boost::thread_group threads;
        void startTask( string name )
        {
            //add new task to vector list           
            mtasks.push_back( task(name) );
            // execute start() on a new thread
            threads.create_thread( boost::bind( &task::start, &mtasks.back()) );
        }
        int tasksTotal()
        {
            return mtasks.size();
        }
        string taskInfo(int i)
        {
            string compstr("Not Completed");
            if ( mtasks[i].completed == true )
            {
                compstr = "Completed";
            }
            return mtasks[i].mname + " " + compstr; 
        }
    private:
        vector<task> mtasks; 
};

int main(int argc, char* argv[])  
{
    string cmd, temp;
    stringstream os;
    bool quit = false;
    taskManager mm;

    cout << "PROMPT>";

    while (quit == false)
    {
        //Wait for a valid command from user
        getline(cin,cmd);

        // Reset stringstream and assign new cmd string
        os.clear(); 
        os << "";
        os << cmd;
        //parse input string
        while (os >> temp) 
        {               
            if ( temp.compare("task") == 0 )
            {
                while (os >> temp) { mm.startTask( temp ); }                     
            }
            if ( temp.compare("info") == 0 )
            { 
                // Returns a list of all completed and not completed tasks
                for (int i = 0; i<mm.tasksTotal(); i++)
                {
                    cout << mm.taskInfo(i).c_str() << endl;
                }                           
            }
            if ( temp.compare("quit") == 0 ){ quit = true; }
        }

        cout << "PROMPT>";
    }

    mm.threads.join_all();      

    return 0;  
};
4

1 に答える 1

4

taskManager::startTaskメソッドのコードに問題があります。

mtasks.push_back( task(name) );
// execute start() on a new thread
threads.create_thread( boost::bind( &task::start, &mtasks.back())

ここでの問題は、新しいタスクをプッシュバックすると、ベクターがスペースを再割り当てする必要があり、古いベクター要素への参照が無効になる可能性があることです。たとえば、次の呼び出しtaskinfoは間違った要素を参照します。古い要素を削除すると、ヒープが何らかの形で破損します。

簡単な修正は、クラスのコンストラクターでベクトル用のスペースを予約することtaskManagerですが、代わりにタスク/タスクマネージャーモデルの設計を変更する必要があります。もう1つの方法はstd::deque、メモリを再割り当てしないため、を使用することです。

于 2012-04-29T15:41:44.783 に答える