7

Ich bin ziemlich neu zu boost :: threads, ich lese die Dokumentation und aber ich habe einige Probleme bei der Anwendung in der Praxis, vielleicht können Sie helfen? Zunächst einmal habe ich die Zeit genommen, eine in sich geschlossene Codeliste zu schreiben, die zwei Arten von Verhalten zeigt, dass ich noch nicht verstehen kann ...boost :: threads Beispiel und heap Korruption Nachricht

Das Programm der Benutzer Befehle zur Ausgabe von 3 verschiedenen erlaubt,

  • Aufgabe [name]
  • info
  • beenden

Der Zweck besteht darin, dass Aufgabe wird einige Arbeit an einem neuen Thread zu starten, kehren Sie dann während der Ausführung der Arbeit zur Eingabeaufforderung zurück. Der Benutzer kann den Befehl info eingeben, um herauszufinden, welche Aufgaben abgeschlossen wurden und welche nicht.

Ich verwende eine Dual-Core-Win7-Maschine und Visual Studio 2008 Express.

Problem 1>

Ausgabe des Befehls, Aufgabe p1 p2 p3 startet 3 Aufgaben ausgeführt werden. Dies kann überprüft werden, indem info ausgegeben wird. Nach ein paar Sekunden ist die Arbeit abgeschlossen, aber aus irgendeinem Grund wird das vervollständigte Flag nicht immer auf 1 oder 2 der Aufgaben gesetzt.

Problem 2>

Quiting das Programm erzeugt dann die folgende Meldung:

Windows-Breakpoint in example.exe ausgelöst hat. Das liegt möglicherweise an einer Beschädigung des Heapspeichers, die auf einen Fehler in example.exe oder einer der geladenen DLLs hinweist. Dies kann auch daran liegen, dass der Benutzer F12 drückt, während example.exe den Fokus hat. Das Ausgabefenster enthält möglicherweise mehr Diagnoseinformationen.

Hoffentlich können Sie dieses Verhalten reproduzieren und helfen.

Vielen Dank im Voraus. 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; 
}; 

Antwort

4

Es gibt ein Problem mit Ihrem Code in der taskManager::startTask Methode:

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

Das Problem hierbei ist, dass wieder eine neue Aufgabe auf dem Druck, Ihr Vektor haben könnte, etwas Platz umverteilt und so entkräftet die Verweise auf Ihre alten Vektorelemente, so werden die folgenden Aufrufe an taskinfo auf die falschen Elemente verweisen. Wenn Sie die alten Elemente löschen, wird Ihr Heap irgendwie beschädigt.

Eine einfache Lösung wäre, etwas Platz für den Vektor im Konstruktor Ihrer Klasse taskManager zu reservieren, aber Sie sollten wahrscheinlich stattdessen das Design Ihres Task/Taskmanager-Modells ändern. Ein anderer Weg wäre, einen std::deque zu verwenden, da dieser Speicher nicht neu zugewiesen wird.

+1

Ein 'std :: deque' würde hier statt" std :: vector "funktionieren, da die Deque keine bestehenden Einträge neu zuweisen wird. –

+0

@JamesCuster yeah gute Idee, fügte es hinzu. – inf

+0

Ich erkannte nicht, dass die std :: vector alten Einträge auf diese Weise neu zugewiesen wurden. Ich war überzeugt, dass das Problem mit meiner boost :: thread Bibliotheksnutzung zusammenhing. – AlexS