2010-12-10 42 views
4

J'ai des affirmations inattendues faillures dans mon code en utilisant une implentation STL vérifiée. Après quelques recherches, j'ai réduit le problème à un push_back dans un vecteur appelé à partir d'un thread différent de celui dans lequel le vecteur a été créé.Vecteur C++, push_back d'un autre thread s'écrase?

Le code de reproduire ce problème est simple:

class SomeClass 
    { 
    private: 
     std::vector<int> theVector; 
    public: 
     SomeClass() 
     { 
      theVector.push_back(1); // Ok 
     } 


     void add() 
    { 
      theVector.push_back(1); // Crash 
    } 
}; 

La seule différence est que SomeClass est instancié de mon thread principal, et ajouter est appelé à partir d'un autre thread. Cependant, il n'y a pas de problème de concurence: dans la forme la plus simple du code que j'ai utilisé pour le dépannage, personne ne lit ou n'écrit à partir de ce vecteur sauf les cas que j'ai mentionnés plus haut.

Tracé dans le code push_back, j'ai remarqué que certaines méthodes de std :: vector comme count() ou size() renvoient garbage, quand elles sont appelées de l'autre thred (méthode "add"), et corrigent les valeurs à partir du thread de création (dans le constructeur par exemple)

Faut-il conclure que std :: vector n'est pas utilisable dans un environnement multithread? Ou y a-t-il une solution à ce problème?

EDIT: suppression volatile

EDIT 2: Pensez-vous qu'il est possible que le problème ne réside pas dans multithread? Dans mon test, add n'est appelé qu'une seule fois (vérifié en utilisant un point de rupture). Si je supprime le push_back du constructeur, je plante toujours. Donc, à la fin, même avec un seul appel à la méthode d'un vecteur, dans une fonction appelée une fois, l'assertion échoue. Par conséquent, il ne peut y avoir de concurence, ou ...?

+2

S'il n'y a en effet aucun vecteur de concurrence devrait fonctionner. S'il y a 2 threads ou plus travaillant avec vector * en parallèle *, cela ne fonctionnera pas. – Drakosha

+1

Êtes-vous dans un environnement où chaque thread a son propre tas? – JimR

+0

Essayez d'appeler 'reserve'. – Fozi

Répondre

2

Si vous pouvez garantir que personne n'écrit ou ne lit le vecteur lorsque vous appelez push_back, il n'y a aucune raison pour que cela échoue. Vous pourriez avoir affaire à une corruption de mémoire de plus haut niveau. Vous devriez vérifier que "this" pointe vers une véritable instance de SomeClass, vérifier ses autres membres, etc.

+0

+1 pour vérifier l'instance de 'SomeClass'. –

+0

Vous avez effectivement raison: le problème n'était pas le vactor ou les threads mais l'instance SomeClass. Merci beaucoup pour vos idées – Dinaiz

1

Si la bibliothèque standard prend en charge le multithreading, l'implémentation est définie. Vous devez lire la documentation pour votre compilateur spécifique.

Additionaly ce que vous pouvez faire est d'ajouter des messages du journal comme dans le code suivant:

class SomeClass 
    { 
    private: 
     volatile std::vector<int> theVector; 
    public: 
     SomeClass() 
     { 
      std::cout << "SomeClass::SomeClass" << std::endl; 
      theVector.push_back(1); // Ok 
     } 
     ~SomeClass() 
     { 
      std::cout << "SomeClass::~SomeClass" << std::endl; 
     } 
     void add() 
     { 
      std::cout << "SomeClass::add" << std::endl; 
      theVector.push_back(1); 
     } 
}; 

Assurez-vous que l'instance de SomeClass est existe toujours lorsque vous appelez add fonction.

1

La plupart des implémentations STL ne sont pas thread-safe. Vous devrez utiliser la synchronisation des threads (par exemple mutex) pour empêcher les deux threads de se piétiner les uns les autres lors de l'accès au vecteur. Fondamentalement, ce que vous devrez faire est de créer une classe qui contient le vecteur et des fonctions de mutex et d'accesseur qui protègent le vecteur pour les opérations de lecture et d'écriture.

+0

@Gene: Je pense que lorsque les gens disent "thread safe", ils veulent dire "capable d'utiliser dans les threads sans rien faire de spécial." –

+0

Cette réponse contient la même erreur que @pts '. Mutex et la synchronisation sont complètement hors de propos ici. –

+0

@John: La définition de Gene est aussi bonne que n'importe laquelle. "Thread safe" est une qualification sans valeur puisque deux personnes ne s'entendent pas sur sa signification. –

7

std::vector est certainement utilisable dans un environnement multithread, à condition de ne pas accéder au vecteur à partir de deux threads à la fois. Je le fais tout le temps sans problème.

Depuis vector n'est pas le problème, vous devez regarder de plus près votre mécanisme de synchronisation, car c'est probablement le problème. J'ai remarqué que vous avez marqué vector comme volatile. Pensez-vous que le faire volatile fournira la synchronisation? Parce que ça ne va pas. See here for more information.

EDIT: à l'origine fournie mauvais lien. Ceci est maintenant corrigé. Désolé pour la confusion.

+0

Désolé, volatile est faux, et, comme mentionné, il ne compile même pas. D – Dinaiz