Multithreading Problem
-
void * subRoutine (void * args) { unsigned int helper, helpen; unsigned int* helping; TrickyThing thread = *((TrickyThing*)args); set<vector<unsigned int> > setA; vector <unsigned int> helps(4); pthread_mutex_lock(&mutex); Matrix Ergebnis(thread.path.c_str()); pthread_mutex_unlock(&mutex); int q = 0; for (int i=0; i<Ergebnis.get_row();++i) { for (vector<unsigned int*>::iterator k = variabel.begin(); k != variabel.end(); ++k) { helping = *k; if (helping[1]!=Ergebnis.get_element(i, thread.column)) continue; if (setA.size()>50000000) { if (thread.column==0) { helper=Ergebnis.get_element(i-1, 1); helpen=Ergebnis.get_element(i, 1); } else { helper=Ergebnis.get_element(i-1, 0); helpen=Ergebnis.get_element(i, 0); } if (helper!= helpen) { pthread_mutex_lock(&mutex); if (q==0) { outfile_set(setA,(thread.secondpath).c_str(),1); q=1; } else { outfile_set(setA,(thread.secondpath).c_str(),0); } setA.clear(); cout << thread.message << " calculates " << i << " of " << Ergebnis.get_row() << " rows..."<< endl << endl; pthread_mutex_unlock(&mutex); } } for (int l=1; l<=helping[0]; ++l) { for (int m=0; m<4;++m) { if (thread.column==m) { helps[m] = helping[l]; } else { helps[m] = Ergebnis.get_element(i, m); } } setA.insert(helps); } } } pthread_mutex_lock(&mutex); if (q==0) { outfile_set(setA,(thread.secondpath).c_str(),1); } else { outfile_set(setA,(thread.secondpath).c_str(),0); } remove (thread.path.c_str()); pthread_mutex_unlock(&mutex); setA.clear(); pthread_exit (0); }edit: nur um dem augenkrebs vorzubeugen und es für etwaige helfer lesbarer zu gestalten. ich selbst hab' heute nacht aber keinen drang mehr, mich da durchzuwurschteln

-
Denke mal vieles ist selbsterklärend einiges wieder um nicht:
Also es wird eine Matrix aus einer Datei eingelesen, dessen Pfad ich durch den Threadaufrufer übergebe. Dieses Angabe und noch mehr befinden sich im struct Trickything. Dann wird die Matrix, die immer aus vier Zahlen pro Reihe besteht, pro Spalte aufgelöst. Ich habe einen Container variabel der Varianten einer Zahl beinhaltet, jede Zeile, in der die Zahl in der aktuellen Spalte vorkommt, wird eine identische Zeile mit den Varianten erstellt. Die Übergabe der Daten sind völlig korrekt, die Funktion selber ist auch korrekt, es lief auch bei Multithreading korrekt, nur wenn ich die Funktion mehrmals hintereinander aufrufe, entsteht ein Speicherzugriffsfehler. Und da wäre ich um Eure Hilfe dankbar?
-
helper, helpen, helping, helps ... willst du uns verarschen?
nenn mal deine variablen so um dass man weiss wozu sie gut sind, mach ein paar kommentare rein was der code tut, und dann poste das ganze nochmal mit den relevanten stellen des restlichen programms.
vielleicht tut es sich dann jmd. an dein programm anzugucken.und bitte schreib doch netterweise dazu WO genau es das programm zerreisst. wenn du das nicht weisst ist das gleich deine nächste aufgabe: finde es raus. genau dafür gibt es debug builds und debugger.
-
hmm was machst du denn mit den pfaden? welche du über die Trickything struktur übergibst? sind diese konstant?
am ende der routine machs du ja sowas:
remove (thread.path.c_str());ist das nich kritisch wenn diu
thread.path.c_str();in mehren trhead verwendest?
nur ne vermutung
-
Jimmie1973 schrieb:
Leseoperationen auf globale Variablen, an den Thread übergebene Variablen oder im Thread erstellten Variabeln werden nich geschützt. Das ist doch korrekt so, oder??
globale Variablen ... wenn sie read only sind, also nicht veraendert werden waehrend ein thread laeuft.
an den Thread übergebene Variablen ... wenn sie per-value uebergeben wurden bzw aus anderen threads nicht schreibend referenziert werden
Thread erstellten Variabeln ... wenn es keine 'static' und keine an andere threads weitergegebene variablen sind.
-
Und wenn man schon auf eine globale Variable zugreifen muss, dann kann man selbigen Vorgang ja ganz kurz durch ne Semaphore absichern.
-
void * subRoutine (void * args) { // Ist die Hilfsvariable für die Varianten unsigned int* helping; // übergibt Variablen, u. a. Thread.path und Thread.secondPath: beides unterschiedliche Dateinamen für jeden erstellten Thread, ergo kein Problem bei remove oder beim Schreiben TrickyThing thread = *((TrickyThing*)args); // Ein Set was die neuen Ergebniszeilen übernimmt set<vector<unsigned int> > setA; // Eine aktuelle Zeile vector <unsigned int> helps(4); pthread_mutex_lock(&mutex); // Die Matrix, die aus einer Datei eingelesen wird Matrix Ergebnis(thread.path.c_str()); pthread_mutex_unlock(&mutex); // q: 1: Die Datei wurde schon mal beschrieben // 0: Die Datei ist unbeschrieben int q = 0; // Erste Schleife die Zeilen der Matrix werden durchgegangen for (int i=0; i<Ergebnis.get_row();++i) { // Der Vector der Varianten wird durchgegangen for (vector<unsigned int*>::iterator k = variabel.begin(); k != variabel.end(); ++k) { helping = *k; // Vergleichen, ob der Wert in der Zeile gleich dem Wert der ersten Zahl ist, wenn nicht soll er die nächste Variante nehmen. Laut gdb entsteht hier ein Fehler. if (helping[1]!=Ergebnis.get_element(i, thread.column)) continue; // Zunächst habe ich ein Stück Code weggelassen, da es nur die Ergebnisse schon vorher wegschreibt. ab hier werden die neuen Ergebniszeilen erstellt for (int l=1; l<=helping[0]; ++l) { for (int m=0; m<4;++m) { if (thread.column==m) { helps[m] = helping[l]; } else { helps[m] = Ergebnis.get_element(i, m); } } setA.insert(helps); } } } pthread_mutex_lock(&mutex); // Schreiben des sets in die Datei if (q==0) { outfile_set(setA,(thread.secondpath).c_str(),1); } else { outfile_set(setA,(thread.secondpath).c_str(),0); } // Löschen der Ursprungsdatei remove (thread.path.c_str()); pthread_mutex_unlock(&mutex); setA.clear(); pthread_exit (0); }
-
hmm was machst du denn mit den pfaden? welche du über die Trickything struktur übergibst? sind diese konstant?
Sind von Thread zu Thread unterschiedlich, deswegen gibt es beim remove wohl kein Problem!
globale Variablen ... wenn sie read only sind, also nicht veraendert werden waehrend ein thread laeuft.
an den Thread übergebene Variablen ... wenn sie per-value uebergeben wurden bzw aus anderen threads nicht schreibend referenziert werden
Thread erstellten Variabeln ... wenn es keine 'static' und keine an andere threads weitergegebene variablen sind.Genau so verstehe ich das auch. Lese die Variablen auch nur!!
-
ich gebe zu thread debugging isdt nicht das einfachste, aber fang doch bitte einfach mal ein mit printf() oder cout zu arbeiten. übergebe dem tread einen eindeutigen identifizierer damit du debugausgaben mit printf() gezielt steuern kannst. prüfe wo es tatsächlich kracht. kommentare und printf() sind die einfachsten debughilfsmittel
anhand dieses codes jedenfalls kann man nur mutmaßen, ich tippe sogar eher auf bugs ausserhalb dieses codes.
-
Wobei man auf den Inhalt der Ausgaben mit printf und cout nicht zuviel geben sollte. Wenn mehrere Threads gleichzeitig darauf zugreifen wird's Buchstabensuppe

-
It0101 schrieb:
Wobei man auf den Inhalt der Ausgaben mit printf und cout nicht zuviel geben sollte. Wenn mehrere Threads gleichzeitig darauf zugreifen wird's Buchstabensuppe

deswegen erwähnte ich ja eine möglichkeit wie man gezielt nur einen thread definieren kann, der debugausgaben macht

-
Hmm.. ich habe genug Ausgaben, die ich nur hier zur Vereinfachung herausgenommen habe. Laut gdb stürzt das Programm in der Zeile 44 ab. Aber irgendwie kann das nicht sein. Denn die entnommen Werte liegen im korrekten Bereich. Das Problem taucht eher mehr im mehrfachen Duchlaufen des Threadprogramms auf. Frage mich da eher, ob ich irgendein Speicherbereich nicht korrekt frei gemacht habe!
-
dann kommentier mal code aus... schritt für schritt... und probier ob es dann mit mehere thread funktioniert..
-
sothis_ schrieb:
ich gebe zu thread debugging isdt nicht das einfachste, aber fang doch bitte einfach mal ein mit printf() oder cout zu arbeiten.
Das nennt sich auch Shotgun Debugging und ist ein beliebtes AntiPattern.

@OP:
Da du anscheinend unter einen unixoidem BS arbeitest, versuch mal helgrind aus der Valgrind-Suite. Die anderen Tools wie z.B. memcheck können dir auch helfen Fehler zu finden, wenn Speicherzugriffsfehler vorkommen.Du solltest außerdem z.B. globale Variablen, übergebene Variablen etc., die von mehreren Threads gelesen werden und sich potenziell ändern können, mit volatile qualifizieren. Das hält den Compiler von gefährlichen Optimierungen (Annahmen über Unveränderbarkeit) im Multithreading Bereich ab.
-
Synchronisier doch zunächst einmal den Zugriff auf jede nicht-Stack-Variable, wenn dann die Methode fehlerfrei durchläuft lockerst du den Zugriff Schritt für Schritt, ab da wo es den Fehler gibt weiß du ja welche Variable zuletzt freigegeben wurde, dann sperr den Zugriff auf alle bis auf diese und wenn es dann immernoch kracht hast du den Übeltäter gefunden.
-
Tippgeber schrieb:
Synchronisier doch zunächst einmal den Zugriff auf jede nicht-Stack-Variable,[...]
Hiermit meine ich natürlich nur die Stack-Variablen die nicht an andere Methoden übergeben werden.
-
Tippgeber schrieb:
Tippgeber schrieb:
Synchronisier doch zunächst einmal den Zugriff auf jede nicht-Stack-Variable,[...]
Hiermit meine ich natürlich nur die Stack-Variablen die nicht an andere Methoden übergeben werden.
Und für wie wahrscheinlich hältst du es, dass der Fehler nach Änderungen in der Synchronisierung noch auftritt
"Der Versuch verändert das Experiment"...
-
7H3 N4C3R schrieb:
Tippgeber schrieb:
Tippgeber schrieb:
Synchronisier doch zunächst einmal den Zugriff auf jede nicht-Stack-Variable,[...]
Hiermit meine ich natürlich nur die Stack-Variablen die nicht an andere Methoden übergeben werden.
Und für wie wahrscheinlich hältst du es, dass der Fehler nach Änderungen in der Synchronisierung noch auftritt
"Der Versuch verändert das Experiment"...
man passt die Umgebung Schrittweise wieder der alten an 
-
idea schrieb:
man passt die Umgebung Schrittweise wieder der alten an 
Super Idee.
Und was ist, wenn das Problem nur in der ursprünglichlen Umgebung auftritt - wie es bei Multithreadingfehlern sehr häufig der Fall ist? Genau das ist Shotgun Debugging.
-
7H3 N4C3R schrieb:
idea schrieb:
man passt die Umgebung Schrittweise wieder der alten an 
Super Idee.
Und was ist, wenn das Problem nur in der ursprünglichlen Umgebung auftritt - wie es bei Multithreadingfehlern sehr häufig der Fall ist? Genau das ist Shotgun Debugging.Während du noch da sitzt und das Problem errätst haben andere das Problem mit ihrer Shotgutn längst erlegt
