7

Я довольно новичок в boost :: threads, я прочитал документацию, но у меня есть некоторые проблемы с ее применением на практике, возможно, вы можете помочь? Прежде всего, я взял время, чтобы написать автономный листинг кода, который демонстрирует 2-х типов поведения, которые я до сих пор не могу понять ...boost :: threads пример и сообщение об ошибке кучи

Программа позволяет пользователю выдавать 3 различные команды,

  • задача [имя]
  • Информация
  • бросить

цель состоит в том, что задача запустит какую-то работу на новом потоке, но затем вернитесь к командной строке во время выполнения работы. Пользователь может дать команду info, чтобы выяснить, какие задачи были выполнены, а какие нет.

Im с использованием двухъядерной машины Win7 и Visual Studio 2008 Express.

Проблема 1>

Выдача команды, задача p1 p2 p3, начинается 3 задачи работает. Это можно проверить, выпустив info. Через несколько секунд работа завершена, однако по какой-либо причине завершенный флаг не всегда задан для 1 или 2 задач.

Задача 2>

помнится программа затем выдает следующее сообщение:

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

Здесь будет работать 'std :: deque', а не' std :: vector', так как deque не перераспределяет существующие записи. –

+0

@JamesCuster да, хорошая идея, добавил. – inf

+0

Я не знал, что std :: vector перераспределил старые записи таким образом, я был убежден, что проблема связана с использованием моего boost :: thread library. – AlexS