2017-04-21 3 views
1

Ich habe eine C++ Struktur wie folgt definiert:Gelegentliche Segmentierungsfehler in einer Struktur Operatorfunktion Überlastung

typedef struct event{ 
int id; 
string name; 
//int arg0; 
QByteArray data; 

bool operator<(const event& e) const 
{ 
    return id < e.id; 
} 

bool operator==(const event& e) const 
{ 
    return id == e.id; 
} 

}Event; 

Ich habe auch eine Karte wie folgt definiert:

map<string, set<Event>> mapOfEventsByString; 

Wenn ich sehen will, wenn ein Event ist auf eine bestimmte Zeichenfolge zugeordnet ich diese Codezeile verwenden:

if(mapOfEventsByString.find(aString)->second.count(event)==1) 
{ 
    //do stuff 
} 

Problem: Manchmal (und ich meine, dass 9/10 mal ich die gesamte Anwendung mit dem exakt gleichen Datensatz ohne Probleme ausgeführt werden kann), erhalte ich einen Segmentation Fault hier:

bool operator<(const event& e) const 
{ 
    return id < e.id; <------- GIVES SEGMENTATION FAULT SOMETIMES 
} 

Nach vielen Versuchen auf den Fehler reproduzieren Während des Debugging konnte ich den Segfault auf diese Zeile lokalisieren. In diesem Szenario wird e.id mit Daten gefüllt und id sagt: "kein solcher Wert".

Hilfe? Danke

+2

Haben Sie in Betracht gezogen (ist es möglich), dass 'mapOfEventsByString.find (aString)' fehlschlagen kann (d. H., 'MapOfEventsByString.end()') zurückgibt? In diesem Fall hat der Rest ein undefiniertes Verhalten. Es könnte bei '->' (bestenfalls) oder sogar bei den folgenden Operationen abstürzen. – Scheff

+2

Nicht das 'typedef struct name {...} name;' ist ein C'ism. In C++ ist der 'typedef' nicht nötig. Sie können einfach 'struct name {...};' haben und 'name' verwenden, ohne es mit' struct' zu qualifizieren, als würden Sie C. – NathanOliver

+1

Ja, Sie müssen den Rückgabewert von map :: find überprüfen, bevor Sie ihn verwenden.Ich vermute von deiner Verwendung von "typedef", dass du aus C land kommst, und das könnte der Grund sein, warum du versucht hast, alles in diese eine Zeile zu quetschen. Ich schlage vor, es in mehreren Zeilen zu tun, z. auto eventKey = mapOfEventsByString.find(aString); if (eventKey != mapOfEventsByString.end() {if (eventKey->second.count(event)==1) {//do stuff}} Verwenden Sie alternativ map :: get, setzen Sie Ihren Aufruf in einen try-Block und fangen Sie out_of_range ab. – tipaye

Antwort

0

Ohne ein Backtrace sind wir nur raten, aber das ist ein starkes Anzeichen dafür, dass das Mitglied id nicht existiert, so dass Sie Speicher zugreifen, sollten Sie nicht. Wenn das Mitglied id nicht vorhanden ist, ist Ihr operator<-Aufruf unterbrochen. Da es durch den unten markierten Teil des Codes aufgerufen wird:

if(mapOfEventsByString.find(aString)->second.count(event)==1) 
//           ^^^^^^^^^^^^^ 

, die mir nahe, dass die unten Ausdruck hervorgehoben nicht sicher auf ein gültiges Objekt verweisen:

if(mapOfEventsByString.find(aString)->second.count(event)==1) 
//         ^^^^^^ 

Der einzige Weg, passieren kann, ist, wenn die unten hervorgehoben dereferenzieren Operation ist ungültig:

if(mapOfEventsByString.find(aString)->second.count(event)==1) 
//         ^^ 

die, wenn sie auftritt, die find ausfällt, Rückkehr mapOfEventsByString.end() (Die nicht dereferenziert werden):

if(mapOfEventsByString.find(aString)->second.count(event)==1) 
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

Ich denke, wenn Sie tatsächlich für find Erfolg überprüfen Sie, dass sehen werden, 1 von 10 mal wurde aString nicht in mapOfEventsByString gefunden.

Lassen Sie uns dies tun, statt:

const auto it = mapOfEventsByString.find(aString); 
if (it != mapOfEventsByString.end() && it->second.count(event) == 1) { 
    // do stuff 
} 

Jetzt können Sie in für, wenn it == mapOfEventsByString.end() einen Haltepunkt setzen und untersuchen, warum der Fund ausfällt. Viel Glück!

Verwandte Themen