_M_ construire null non valide erreur lorsque vous essayez de mettre en œuvre multi threaded file d'attente
Je suis en train de mettre en œuvre une file d'attente de priorité à l'aide à l'aide d'une simple approche linéaire, comme expliqué dans L'Art de la programmation Multiprocesseur. Je suis novice en c++ et ont de la difficulté à le dépannage.
J'ai mis en place deux classes de modèle et de suis de les tester à l'aide d'une simple méthode de test. Comme je ne suis pas en mesure de cerner le point de l'erreur, je suis collage de tous les trois classes ci-dessous pour référence.
Je sais que _M_ construct null not valid
vient quand on tente de construire une chaîne à l'aide de nullptr
, mais je ne suis pas sûr de l'endroit où je fais.
Les trois classes créées sont donnés ci-dessous:
bin.h
#include <mutex>
#include <deque>
#include <memory>
#include <iostream>
using namespace std;
namespace priority
{
template<typename T>
class Bin
{
private:
std::deque<T> v;
std::mutex m;
public:
Bin() {
}
Bin(const Bin &o) {
}
const Bin &operator=(const Bin &other) {
return *this;
}
void put(T item) {
std::lock_guard<std::mutex> lock(m);
v.push_back(item);
}
T *get() {
std::lock_guard<std::mutex> lock(m);
if (v.size() == 0) {
return nullptr;
}
else {
T val = v.front();
T *ptr_val = &(val);
v.pop_front();
return ptr_val;
}
}
bool isEmpty() {
std::lock_guard<std::mutex> lock(m);
return v.size() == 0;
}
};
}
SimpleLinear.h
#include <mutex>
#include <vector>
#include <memory>
#include "Bin.h"
namespace priority
{
template<typename T>
class SimpleLinear
{
private:
int range;
std::vector<Bin<T>> pqueue;
public:
SimpleLinear(int range){
this->range = range;
for (int i = 0; i < range; i++)
{
pqueue.push_back(Bin<T>());
}
}
void add(T item, int key) {
pqueue[key].put(item);
}
T removeMin() {
for (int i = 0; i < range; i++)
{
T *item = pqueue[i].get();
if (item != nullptr) {
return *item;
}
}
return nullptr;
}
};
}
test.cpp
#include <iostream>
#include <vector>
#include <thread>
#include <algorithm>
#include "SimpleLinear.h"
using namespace std;
using namespace priority;
void te(SimpleLinear<string> s, int thread_id) {
s.add("sundar"+to_string(thread_id), thread_id);
s.add("akshaya"+to_string(thread_id), 3);
s.add("anirudh"+to_string(thread_id), 1);
s.add("aaditya"+to_string(thread_id), 5);
cout << s.removeMin() << endl;
cout << s.removeMin() << endl;
cout << s.removeMin() << endl;
}
int main(int argc, char const *argv[])
{
SimpleLinear<string> s(100);
std::vector<std::thread> v;
for (int i = 0; i < 100; i++)
{
//if (i % 2 == 0)
v.push_back(thread(te, std::ref(s), i));
//else
//v.push_back(thread(t, std::ref(s), i));
}
for_each(v.begin(), v.end(), std::mem_fn(&std::thread::join));
return 0;
}
J'obtiens le message d'erreur:
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_M_construct null not valid
terminate called recursively
terminate called recursively
terminate called recursively
Aborted (core dumped)
- Si vous souhaitez créer une chaîne vide, il suffit de faire par exemple
std::string()
. Ou pour un type génériqueT
neT()
. removeMin
est de retournullptr
. Changer dereturn T();
- Votre problème est que vous en pensez (je suppose)
nullptr
signifie "sans objet". C'est faux,nullptr
signifie simplement "pointeur null". En C++ (contrairement à des langages comme C# et Java) il n'y a pas une telle chose comme "sans objet". - en fait.. je suis vraiment désolé de ce code.. je 'ai posté dans le mauvais code... je l'ai mis à jour
- SimpleLinear n'est pas thread-safe - vous êtes en train d'ajouter des articles à partir de plusieurs threads dans un std::vector sans verrouillage
- En linéaire simple, je suis juste l'appel de la mettre de la Corbeille de droit qui est thread-safe, donc dois-je verrouiller il ainsi?
pqueue[key].put(item);
est un appel à mettre sur pqueue. pqueue n'est pas thread-safe. Bin n'a pas besoin d'être thread-safe, vous n'avez pas plusieurs threads tentent de lecture/écriture à une instance en même temps- Maintenant, après votre montage, vous avez un comportement indéfini au lieu de cela, comme vous le retour des pointeurs vers des variables locales. Ne pas mise à jour de votre question pour "réparer" le code. Que tirer le tapis sous nos pieds, pour ainsi dire. Elle permet à nos commentaires et les réponses possibles de mal.
Vous devez vous connecter pour publier un commentaire.
Une raison pour laquelle il se bloque, c'est que dans
SimpleLinear<T>::removeMin
quandT
eststd::string
,return nullptr
construit une chaîne denullptr
.basic_string::_M_construct null not valid
dit en faitque
std::string(nullptr)
a été invoquée.Une autre raison, il peut se bloquer, c'est que
get
fonction renvoie un pointeur sur une variable locale. Les variables locales sont détruits lorsque la fonction retourne. Cela conduit à un comportement indéfini.Un correctif:
Et à l'appeler comme:
Bin.h