7

我很興奮boost :: threads,我閱讀文檔,但我在實踐中遇到了一些麻煩,也許你可以幫忙嗎?首先,我已寫了一個自包含的代碼清單演示了2種類型的行爲,我還不能明白的時候......boost :: threads示例和堆腐敗消息

該程序允許用戶發佈3個不同的命令,

  • 任務[名]
  • 資訊
  • 退出

的目的是,任務將推出一個新的線程一些工作,但在執行工作時返回命令提示符。用戶可以通過info命令找出哪些任務已完成,哪些尚未完成。

我使用雙核Win7機器和Visual Studio 2008 Express。

問題1>

發出命令,任務P1 P2 P3,開始運行3個任務。這可以通過發行info來檢查。幾秒鐘後,工作完成,但由於某種原因,完成的標誌並不總是在1或2個任務上設置爲真。

問題2>

GRUB.EXE返回該程序然後產生以下消息:

Windows已經引發了example.exe一個斷點。這可能是由於堆損壞引起的,這表明example.exe或其中已加載的任何DLL都存在缺陷。 這可能也是由於用戶按下F12而example.exe具有焦點。 輸出窗口可能有更多的診斷信息。

希望你能重現這種行爲和幫助。

在此先感謝。 Alex。

//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

沒有您的代碼在taskManager::startTask方法的一個問題:

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

這裏的問題是,在推回新的任務,你的載體可能需要重新分配一些空間,這樣的無效引用您的舊矢量元素,則以下對taskinfo的調用將引用錯誤的元素。當你刪除舊的元素時,堆會以某種方式被損壞。

一個簡單的解決方法是在taskManager類的構造函數中爲向量保留一些空間,但是您應該改爲改變task/taskmanager模型的設計。另一種方法是使用std::deque,因爲那個人不會重新分配內存。

+1

因爲deque不會重新分配現有條目,所以'std :: deque'可以在這裏工作而不是'std :: vector'。 –

+0

@JamesCuster是個好主意,添加它。 – inf

+0

我沒有意識到std :: vector以這種方式重新分配舊條目,我確信問題出在boost :: thread庫的使用上。 – AlexS