Segmentation Fault - wie der Sache auf die Schliche kommen?
-
Da hilft nur systematisches Testen/Debuggen. DU musst halt versuchen Programmcode auszuschließen bis du den Fehler findest. Aber da du einen Zugriffsfehler hast, würde ich bei Arrays beginnen. Ohne Code etc. bekommst du wohl nicht viel hilfe und musst einfach suchen.
-
Habe die Fehlerursache wohl etwas eingegrenzt - es scheint damit zu tun zu haben, wenn ich einen Vektor als Parameter an den Konstruktor übergebe.
out += " Eingelesene Sequenzen: \n"; vector<string> seqs = javamain.getSequencesList(); for ( int i = 0; i < seqs.size(); i++ ) { out += " " + seqs.at( i ) + "\n"; } out += "\n"; // Aufruf H2r h2r( seqs ); // TODO Check ob aendern auf callbyreference //h2r.computeH2r();Wenn ich die h2r-Instanz nicht erzeuge läuft es ohne Fault, sonst knallts!
-
Jay1980 schrieb:
Habe die Fehlerursache wohl etwas eingegrenzt - es scheint damit zu tun zu haben, wenn ich einen Vektor als Parameter an den Konstruktor übergebe.
Warum zeigst du uns dann nicht den Konstruktor?
edit: Und verlass dich nicht zu sehr auf "Wenn ich dies rausmache, dann geht es". Speicherfehler verursachen sehr oft undefiniertes Verhalten, da kann man sich nicht auf solche Vorgehensweisen verlassen.
-
Okay, hier ist der Teil des Konstruktors der gleich den Fehler hervorruft:
#include "h2r.h" #include <iostream> #include <vector> using namespace std; H2r::H2r( vector<string> seqList ){ // Debuglevel extern string log; if ( log == "1" ){ cout << "DEBUG: H2r - Konstruktor() ... "; }Die Variablen log ist in der Datei main.cpp angelegt - ich wollte diese als globale Variable, damit diese von überall zugreifbar ist.
// Konfiguration hier und in Javamain-Objekt //const string log = "0"; // keine Ausgaben anzeigen const string log = "1"; // volles Logging //const string test = "0"; // keine Tests const string test = "1"; // alle Regressionstests ablaufen lassen string out = ""; // Funktionsprototypen void testJavamainGetSequencesList(); /* * */ int main(int argc, char** argv) { // Konfigurationsobjekt holen Javamain javamain; // Konstruktor Breymann2009 S. 155, globale Variable if ( test == "1" ) { // Behelfs-Testsuite cout << "\n"; cout << " ************************************** \n"; cout << " Testmodus H2r - HSRP-Ermittlung \n"; cout << " ************************************** \n"; cout << "\n"; // Testmethoden testJavamainGetSequencesList(); } if ( log == "1" ) { // Debugversion Breymann S. 133 cout << "\n"; cout << " ************************************** \n"; cout << " Log-Modus H2r - HSRP-Ermittlung \n"; cout << " ************************************** \n"; cout << " \n "; }
-
Jay1980 schrieb:
out += " Eingelesene Sequenzen: \n"; vector<string> seqs = javamain.getSequencesList(); for ( int i = 0; i < seqs.size(); i++ ) { out += " " + seqs.at( i ) + "\n"; } out += "\n";Du weisst, dass das ineffizient ist (weil strings nicht gebuffert werden) und das nächste mal, wenn du alles neu schreibst, besser so geschrieben gehört:
std::ostringstream out; out << " Eingelesene Sequenen: "; for (std::vector<std::string>::iterator it=seqs.begin(); it!=seqs.end(); ++i) out << "\n " << *it; out << "\n\n";oder noch besser:
std::ostringstream out; out << " Eingelesene Sequenen: \n "; std::copy(seqs.begin(), seqs.end(), std::ostream_iterator(out, "\n "); out << "\n";
-
Der Fehler liegt IMHO beim
extern.
Wenn du diese Zeile aus dem Konstruktor rausnimmst, und unter dein hässliches `using namespace std;` schreibst, sollte es gehen.
Vllt. geht es auch, wenn du es am Ort lässt und
extern string ::log;schreibst, aber da kenne ich mich nicht so genau aus.
Globale Variablen deklariert man eh lieber in einem Headerfile, aber meistens kapselt man die über eine Funktion mit einem statischen Objekt. Dass alles nicht threadsafe ist, macht bei dir vermutlich nichts aus.
-
Danke ich werde direkt etwas nachlesen. Hast du vielleicht einen Link zu einem Tutorial oder Artikel, der zeigt wie man effizient mit Strings arbeitet - ich habe schon etwas geschaut, aber es ist für mich schwierig aufgrund der Vielzahl von String-Bibliotheken die Übersicht zu behalten, oft kommen bei Google auch die Unterlagen an vorderster Stelle, die relativ alt sind - da kann ich nicht einschätzen, ob die noch aktuell sind.
Auch die Sache mit den globalen Daten in eigenen Headerfiles lese ich nach - da sollte ich leichter was finden.
Ich habe gelesen using namespace ist voll ok in cpp-Dateien und nur in h-Dateien soll man dies nicht nutzen?!
-
Am besten garnicht using namespace verwenden. using std::... reicht auch für einzelne Funktionen. Und wie du sagtest, nie im Header verwenden

-
HighLigerBiMBam schrieb:
Am besten garnicht using namespace verwenden. using std::... reicht auch für einzelne Funktionen
Warum nicht?
-
Um Namenskonflikte zu vermeiden. Es ist durchaus möglich, dass es in zwei verschiedenen Namensräumen(Bibliotheken) Funktionen mit gleichen Parametern gibt, die auch gleich heißen. Und eigene Funktionen mit z.B. den namen copy oder swap sind schnell geschrieben und using namespace std ist da sicher nicht hilfreich

-
Jay1980 schrieb:
Ich habe gelesen using namespace ist voll ok in cpp-Dateien und nur in h-Dateien soll man dies nicht nutzen?!
Solche Aussagen sind wie alle generalisierenden Aussagen völliger Blödsinn. (Wenn auch diese natürlich keine schlechte Ausgangslage ist). Aber viel wichtiger ist, zu verstehen, was using denn genau bedeutet rsp. bewirkt.
Dann folgt alles andere wie selbstverständlich.
Das Problem mit using ist, dass du bei grösseren Projekten mit mehreren namespaces arbeiten wirst und entsprechend schnell ein kleines Chaos bekommst, welches Objekt jetzt zu welchem namepace gehört. (Weil da dann eben nur string steht, und nicht std::string, kannst du dann im File suchen gehn, welchen namespace dass du denn jetzt wieder gerade verwendest und um welches Objekt dass es sich wirklich handelt).
In den .cpp-files ist das noch einigermassen problemlos möglich, aber wenn du die Direktive in nem Header File verwendest, dann musst du um die namespace-Frage zu klären auch immer noch gleich alle header files durchforsten, die allenfalls selber wieder headerfiles included haben usw usw... du siehst das Problem? Ausserdem erinnerst du dich zu einem späteren Zeitpunkt unter Umständen nicht mehr, dass du das using im header hast, includest deine geile alte Klasse in ein neues Projekt und weil du da mit namespaces wieder fahrig umgegangen bist, bringt dir die using direktive ausm alten header deine ganzen neuen namespaces durcheinander... Und du wunderst dich dann warum plötzlich nicht mehr auf das Objekt zugegriffen wird das doch vorher gerade noch so prima funktioniert hat...
-
HighLigerBiMBam schrieb:
Um Namenskonflikte zu vermeiden. Es ist durchaus möglich, dass es in zwei verschiedenen Namensräumen(Bibliotheken) Funktionen mit gleichen Parametern gibt, die auch gleich heißen. Und eigene Funktionen mit z.B. den namen copy oder swap sind schnell geschrieben und using namespace std ist da sicher nicht hilfreich

Und? Dann benutze ich in dem Fall eben kein using. Aber warum sollte ich mir bei überschaubaren Quelltexten diese Bequemlichkeit nicht gönnen? Es ist ja eher selten, dass man in einer einzelnen Quelltextdatei mehr als 1-2 verschiedene Namensräume benutzt.