2016-11-07 4 views
-1
tour_indexes.clear(); 
for (int i=0; i<num_of_cities; i++) 
{ 
    tour_indexes.push_back(i); 
} 

mt19937 gen(random_engine()); 
uniform_real_distribution<> dis(0, 1); 

// Sort indexes based on comparing values in tour. Choose at random if equal 
sort(tour_indexes.begin(), tour_indexes.end(), 
    [&tour, &dis, &gen](int &i1, int &i2) 
{ 
    if (tour[i1] == tour[i2]) 
    { 
     return dis(gen) < 0.5; 
    } 
    return tour[i1] < tour[i2]; 
}); 

Das gibt mir eine segfault auf tour[i1] == tour[i2], und wenn ich finde, das Debuggen, dass es ist, weil i2 ist manchmal (scheinbar nicht deterministisch) viel größer als es sein sollte. ZB 403163787 (es variiert), wenn tour_indexes ist zB 0 - 20 (und ich habe zur Fehlerzeit überprüft, dass tour_indexes enthält nicht i2).C++ Art Iteration manchmal gibt falschen Wert

Dies alles geschieht in einer Member-Funktion in einer Klasse, die die Elementvariable tour_indexes enthält. Das Klassenobjekt befindet sich in einem shared_ptr, wenn dies relevant ist. Irgendwelche Ideen, was könnte das Problem sein? Vielen Dank.

+1

Können Sie bitte versuchen, ein [minimales, vollständiges und überprüfbares Beispiel] zu erstellen (http://stackoverflow.com/help/mcve) und uns zeigen? Einschließlich der Definition und Initialisierung von 'tour' und' num_of_cities'. –

+0

@Someprogrammerdude: Ja, im Prinzip. In der Praxis bedeutet "segfault from std :: sort" mindestens 99% der Zeit "mein Vergleichsoperator ist nicht gültig". –

Antwort

4

Ihr Komparator bietet keine streng schwache Reihenfolge. Speziell, wenn tour[i1] == tour[i2] gibt es eine 50/50 Chance, dass es wahr oder falsch zurückgibt und die Antwort ist nicht stabil (es muss sein).

Wenn Ihre Vergleichsfunktion keine strenge schwache Ordnung liefert, ist das Verhalten undefiniert, und ein seg-Fehler ist ein plausibles Verhalten.

Ich empfehle die Verwendung return i1 < i2; Dies wird die Krawatte in einer stabilen Weise zu brechen.

Alternativ besteht keine Notwendigkeit, die Verbindung zu unterbrechen. Verwenden Sie einfach

[&tour](int i1, int i2) 
{ 
    return tour[i1] < tour[i2]; 
} 

std::sort ganz mit einer schwachen Ordnung glücklich ist; Das bedeutet, dass sowohl cmp(i1,i2) als auch cmp(i2,i1) false zurückgeben können. Was sie nicht bewältigen kann, ist, dass beide True zurückgeben (oder zwei Aufrufe mit denselben Argumenten, die andere Werte zurückgeben).

1

Entfernen Sie die Randomisierung im Vergleichsoperator. Vielleicht scheitert die Art Algortihm, weil sowohl i1 < i2 als auch i2 < i1 wahr sein können, wenn Elemente gleich sind.

sort gibt bereits eine zufällige Reihenfolge aus, wenn eal element und stable_sort eine deterministische Reihenfolge von gleichen Elementen im Array ergeben.

+0

Danke! Ich wusste nicht, dass eine Art eine zufällige Antwort gibt, wenn sie gleich ist, obwohl sie jedes Mal dieselbe Antwort zu geben scheint. – Freddard

+0

Es gibt keine * zufällige * Antwort. Es gibt eine * unberechenbare * Antwort. Es gibt nichts im Standard, um 'std :: sort' zu verbieten, indem einfach' std :: stable_sort' aufgerufen wird. In der Praxis würde ich erwarten, dass "std :: sort" nur die Antwort gibt, die der Quicksort-Algorithmus gibt. –

+0

@Freddard - Schade, dass Sie Ihr Programm nicht unter Visual Studio-Debug-Runtime ausgeführt haben, da es dieses Problem durch zweimaliges Aufrufen des 'sort'-Funktors erkennt, um festzustellen, ob der Rückgabewert mit den Argumenten identisch ist Die Antwort war die gleiche, das Programm hätte mit einer Aussage angehalten. – PaulMcKenzie

Verwandte Themen