[Gelöst] String::operator+= im Konstruktor liefert einen Segmentation Fault
-
Morgen,
beim längst überfälligen Umstellen von
#definenachconst- ein Dank an Scott Mayers - stoße ich ein sich mir nicht erschließen wollendes Problem.Es liegt folgender Quellcode vor:
constats.h// Include Guards, Includes, Konstanten, Enums const std::string FILE_CONFIG = "config.xml"; // ...Konstruktor in gameConfig.cpp
GameConfig::GameConfig() : path_("") // restliche Initializer List { #ifdef UNIX path_ = getenv("HOME"); path_ += "/.Rostsommernacht/"; std::string mkdir = "if [ ! -d "; mkdir += path_; mkdir += " ]; then mkdir "; mkdir += path_; mkdir += "; fi"; system(mkdir.c_str()); #endif path_ += FILE_CONFIG; // Hier liegt laut Debugger gdb das Problem. load(); }Ursprünglich war
FILE_CONFIGdurch#definedefiniert und auch, wenn ich es per Hand inpath_ += "config.xml";umändere, funktioniert alles so, wie es soll.Doch mit dem derzeitigen Code bricht das Programm im Debugger mit folgender Fehlermeldung ab:
Program received signal SIGSEGV, Segmentation fault.
size (this=0x62dad0)
at /usr/src/debug/gcc-4.6.2-20111027/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/basic_string.h:711
711 { return _M_rep()->_M_length; }Wie gesagt, kann ich mir dieses Verhalten nicht erklären und bitte um Hilfe.
Als Compiler nutze ichgcc-Version 4.6.2 20111027 (Red Hat 4.6.2-1) (GCC)mit C++11.Mit freundlichen Grüßen,
KiEDIT:
Der Codeteil im#ifdef-Block scheint das Problem übrigens nicht zu beeinflussen. Ein Auskommentieren sorgt jedenfalls nicht dafür, dass der Fehler nicht mehr auftritt.
-
Ist path_ ein std::string oder ein cstring?
-
path_ ist ein std::string
-
Was passiert, wenn du
const char FILE_CONFIG[] = "config.xml";verwendest?
-
Ich hatte einen ähnlichen Fall, vieleicht gilt das auch für Dich.
Ich hatte zwei statische Objekte und der Konstruktor des einen hat die andere benutzt. Dummerweise wurde dessen Konstruktor noch gar nicht aufgerufen.
Was versprichst Du Dir davon, wenn Du "config.xml" in eine const std:string instanz reinschreibst? Ein const char * hätte es auch getan.
mfg Martin
-
Ich war der Ansicht, ein std::string würde sich besser handhabe.
Wenn ich aus FILE_CONFIG als Char-Array deklariere, funktioniert alles so, wie es soll.
Das heißt wohl, es ist ratsamer und "einfacher", bei konstanten Zeichenketten Char-Array zu nutzen?
-
Es wäre ratsam, dein GameConfig Objekt nicht statisch zu machen.
-
Das GameConfig Objekt ist nicht statisch, aber global.
Jetzt bitte kein Shitstorm, ich weiß, dass wie geschätzte 99% der hiesigen Programmierer zu globalen Variablen stehen.
-
Das Problem ist einfach, dass die Initialisierungsreihenfolge globaler Objekte, die sich nicht in der selben Übersetzungseinheit befinden, unbestimmt ist. In Deinem Fall wird einfach GameConfig vor FILE_CONFIG konstruiert.
Unter anderem deshalb werden globale Variablen in C++ besonders verteufelt.
Lösung: Lass die Konstanten global, nutze aber für die Objekte ein Pattern wie das (Meyers-)Singleton.
-
Werde ich versuchen, notfalls nutze ich sonst die bereits vorgeschlagenen Char-Arrays.
Danke für die Hilfe

-
Nein, GameConfig ist auch kein Singleton. Was machst du denn, wenn du mal noch eine Configdatei hast? Und Fehlerbehandlung ist bei Variablen mit statischer Lebenszeit auch ätzend. Also:
GameConfig::GameConfig(const std::string& s) { // .. } int main() { try { GameConfig main_config("config.xml"); // Game loop } catch ( /* */ ) { } }Und wenn dann wirklich nahezu jede Funktion an dieses Objekt muss, kannst du immer noch einen globalen Pointer darauf initialisieren. Aber das würde ich nur im Notfall machen.