[gelöst] "Speicherzugriffsfehler" beim Schreiben in eine Datei



  • theta schrieb:

    Und wie kommst Du darauf, dass es vor dem 1. recv(..) ist?
    Und wenns so ist, dann debugge doch einfach.

    Durch Debug-Meldungen 😉

    mfg D3lta



  • D3lta schrieb:

    Doch, ich prüfe bei jedem Aufruf auf den RetVal -1, aber in der class Socket, auf welcher diese hier basiert. 🕶

    Und du wirfst schön brav socket_error's?



  • 314159265358979 schrieb:

    D3lta schrieb:

    Doch, ich prüfe bei jedem Aufruf auf den RetVal -1, aber in der class Socket, auf welcher diese hier basiert. 🕶

    Und du wirfst schön brav socket_error's?

    Ja, mit meiner Exception-Class 😃
    Aber es wird keine geworfen...

    mfg D3lta



  • D3lta schrieb:

    theta schrieb:

    Und wie kommst Du darauf, dass es vor dem 1. recv(..) ist?
    Und wenns so ist, dann debugge doch einfach.

    Durch Debug-Meldungen 😉

    mfg D3lta

    Ich würds durchsteppen.



  • theta schrieb:

    D3lta schrieb:

    theta schrieb:

    Und wie kommst Du darauf, dass es vor dem 1. recv(..) ist?
    Und wenns so ist, dann debugge doch einfach.

    Durch Debug-Meldungen 😉

    mfg D3lta

    Ich würds durchsteppen.

    Ich benutze den gcc-Kompiler 😃
    Außerdem habe ich mit Debug-Meldungen den Fehler weitesgehend ausgemacht, ich makiere den Fehler gleich im 1. Post.

    mfg D3lta

    EDIT: makiert 🙂



  • Ich habe weiter nach dem Fehler gesucht und verdächtige nun Socket_Server::accept(), den Fehler zu verursachen, deswegen habe ich den Startpost mit meinem aktuellen Source versehen und den Fehler in die main.cpp geschrieben.

    mfg Δ3lta

    P.S.: Gibt es in dem Forum hier so eine Art Spoiler (Womit man Text verstecken kann, aber bei Mausklick sichtbar wird)? Ich habe so etwas bisher noch nicht gefunden...


  • Mod

    D3lta schrieb:

    P.S.: Gibt es in dem Forum hier so eine Art Spoiler (Womit man Text verstecken kann, aber bei Mausklick sichtbar wird)? Ich habe so etwas bisher noch nicht gefunden...

    Nein, wozu? Wenn du den Lesefluss nicht durch unnötig lange Codestücke unterbrechen möchtest, dann benutz' externe Pastebins. Die kann man zur Not auch als Ersatz für "echte" Spoiler benutzen.



  • SeppJ schrieb:

    D3lta schrieb:

    P.S.: Gibt es in dem Forum hier so eine Art Spoiler (Womit man Text verstecken kann, aber bei Mausklick sichtbar wird)? Ich habe so etwas bisher noch nicht gefunden...

    Nein, wozu? Wenn du den Lesefluss nicht durch unnötig lange Codestücke unterbrechen möchtest, dann benutz' externe Pastebins. Die kann man zur Not auch als Ersatz für "echte" Spoiler benutzen.

    Hätte ja sein können, dass es so etwas gibt...

    mfg D3lta



  • Wenn Du ein minimales Bsp. machst, das den Kompiliert, Linkt und den Fehler zeigt tu ichs dir debuggen...



  • theta schrieb:

    Wenn Du ein minimales Bsp. machst, das den Kompiliert, Linkt und den Fehler zeigt tu ichs dir debuggen...

    Naja, das ist bisher nur die Linux-Version.
    Die Klasse Socket allein hat gut funktioniert, doch jetzt habe ich einfach nur noch auf die Klasse Socket die serverorientierte Klasse socket_server draufgesetzt und was passiert: es funktioniert nicht...
    kannst du mir ein programm auf Linux sagen, womit ich das Programm durchsteppen kann?

    mfg D3lta

    P.S.: Was genau besagt das Wort "debuggen" in diesem Kontext?
    Ich kenne es nur als "Fehler beseitigen"...



  • P.S.: Was genau besagt das Wort "debuggen" in diesem Kontext?
    Ich kenne es nur als "Fehler beseitigen"...

    Mit debuggen habe ich durchsteppen gemeint. War etwas salop, sorry.



  • theta schrieb:

    P.S.: Was genau besagt das Wort "debuggen" in diesem Kontext?
    Ich kenne es nur als "Fehler beseitigen"...

    Mit debuggen habe ich durchsteppen gemeint. War etwas salop, sorry.

    Macht nichts 😉
    Weißt denn jemand einen guten Debugger für Linux?

    mfg D3lta



  • gdb?



  • theta schrieb:

    gdb?

    Danke, ich probiere es mal, den Fehler damit zu finden.

    mfg D3lta



  • Das durchsteppen mit gdb (danke für den Tip 😉 ) hat ergeben, dass in den Funktionen Socket_Server::recv() und Socket_server::close() abstürzt, aber nicht bei Socket_Server::accept() oder Socket_Server::create()
    Also hier ist der Code von logger.h && logger.cpp:

    logger.h

    /*****************
    ***** logger *****
    ******************
    
    loggt meldungen eines Programms in
    eine Datei
    
    *****************/
    
    #ifndef LOGGER_H
    #define LOGGER_H
    #include <fstream>
    #include <string>
    #include <ctime>
    
    using namespace std;
    
    class Logger
    {
    private:
    	string file;
    	fstream log;
    	time_t t_raw;
    	struct tm *time_tm;
    
    public:
    	Logger(const string filename) :file(filename), log(file.c_str(), ios::out|ios::app) 
    	{write("----- START -----", -1);}
    	~Logger() {write("-----  END  -----\n", -1); log.close();}
    	void write(const string msg, int priority=0);
    	//operator<< (const string msg);
    };
    
    //#include "logger.cpp"
    #endif
    

    logger.cpp

    //logger.cpp
    #include "logger.h"
    
    using namespace std;
    
    void Logger::write(const string msg, int priority) 
    {//-1=kein Tag,  0=normale Meldung, 1=Warnung, 2=Error, 3=Fatal Error
    	//t_raw = time(NULL);//(&time_raw);
    	//time_tm = localtime(&t_raw);
    	//Timestamp schreiben(mit vorangehenden Nullen
    	log << "["; 
    	/*if(time_tm->tm_hour<10) log << ("0"); else log << (""); 
    	log << time_tm->tm_hour << ":"; 
    	if(time_tm->tm_min<10) log << ("0"); else log << ("");
    	log << time_tm->tm_min << ":" ;
    	if(time_tm->tm_sec<10) log << ("0"); else log << ("");
    	log << time_tm->tm_sec << "]  "; */
    	//Level ausgeben
    	switch(priority)
    	{
    	case -1:
    		//kein Tag
    		break;
    	case 0:
    		//Information
    		log << "-----  INF  -----  ";
    		break;
    	case 1:
    		//Warnung
    		log << "-----  WAR  -----  ";
    		break;
    	case 2:
    		//Fehler
    		log << "----- ERROR -----  ";
    		break;
    	case 3:
    		//Schwerwiegender Fehler (Fatal Error)
    		log << "----- FTERR -----  ";
    		break;
    	default:
    		//Alles andere
    		log << "----- ERROR ----- Unbekannte Priorität";
    		return;
    		break;
    	}
    	//Meldung schreiben
    	log << msg << endl;
    }
    

    Hier ist noch die Ausgabe meines Debugs mit gdb:

    GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
    Copyright (C) 2010 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "i686-linux-gnu".
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>...
    Reading symbols from /home/lennart/C++/Chat/Chat...done.
    (gdb) break 20
    Breakpoint 1 at 0x8049223: file main.cpp, line 20.
    (gdb) run
    Starting program: /home/lennart/C++/Chat/Chat 
    
    Breakpoint 1, main (argc=1, argv=0xbffff434) at main.cpp:20
    20				cli.recv(s);
    (gdb) step
    Socket_Server::recv (this=0xbffff324, s=...) at socket_server.cpp:65
    65	{
    (gdb) 
    68			log->write("Anfang");
    (gdb) 
    Logger::write (this=0x804c05d, msg=..., priority=0) at logger.cpp:11
    11		log << "["; 
    (gdb) 
    
    Program received signal SIGSEGV, Segmentation fault.
    0x001aec78 in std::basic_ostream<char, std::char_traits<char> >::sentry::sentry(std::basic_ostream<char, std::char_traits<char> >&) ()
       from /usr/lib/i386-linux-gnu/libstdc++.so.6
    (gdb) quit
    

    Ich hoffe ihr könnt mir sagen, warum der Fehler nur bei dieser Funktion auftaucht...

    mfg D3lta

    P.S.: Wenn ich die Zeitfunktionen nicht auskommentiere, erhalte ich folgendes Debug-Ergebnis:

    [ ... genauso wie vorher ...]
    
    (gdb) step
    Socket_Server::recv (this=0xbffff324, s=...) at socket_server.cpp:65
    65	{
    (gdb) 
    68			log->write("Anfang");
    (gdb) 
    Logger::write (this=0x804c25d, msg=..., priority=0) at logger.cpp:8
    8		t_raw = time(NULL);//(&time_raw);
    (gdb) 
    
    Program received signal SIGSEGV, Segmentation fault.
    0x08049e09 in Logger::write (this=0x804c25d, msg=..., priority=0)
        at logger.cpp:8
    8		t_raw = time(NULL);//(&time_raw);
    (gdb) quit
    

    EDIT: Ich habe festgestellt, dass write an der Stelle, wo der Fehler passiert, nicht auf die pritvate-Objekte der Klasse Logger zugreifen kann. 😕 Hat jemand eine Erklärung dafür? 😞
    Wenn ich das Schreiben des Logs auskommentiere funktioniert es, aber was ist der Fehler und warum taucht er nur bei den 2 Funktionen auf?



  • Socket_Server::recv (this=0xbffff324, s=...)
    

    Die Adresse kommt mir ein wenig komisch vor. Hab aber mit Linux auch keine Erfahrung.

    Ansonsten... wenn du das Ding interaktiv im Debugger durchsteppen kannst, dann bleibt er dir ja normalerweise bei Fehlern ala SIGSEGV stehen. Und dann kannst du dir den Callstack ansehen, die ganzen Variablen angucken etc.
    Oder meinst du mit "Ich habe festgestellt, dass write an der Stelle, wo der Fehler passiert, nicht auf die pritvate-Objekte der Klasse Logger zugreifen kann" dass genau das nicht geht?

    Hast du zum Durchsteppen im Debugger (was ich normalerweise übrigens auch "debuggen" nenne :)) auch die Optimierungen deaktiviert? Also eine "Debug Konfiguration" gebaut?



  • hustbaer schrieb:

    Socket_Server::recv (this=0xbffff324, s=...)
    

    Die Adresse kommt mir ein wenig komisch vor. Hab aber mit Linux auch keine Erfahrung.

    Ansonsten... wenn du das Ding interaktiv im Debugger durchsteppen kannst, dann bleibt er dir ja normalerweise bei Fehlern ala SIGSEGV stehen. Und dann kannst du dir den Callstack ansehen, die ganzen Variablen angucken etc.
    Oder meinst du mit "Ich habe festgestellt, dass write an der Stelle, wo der Fehler passiert, nicht auf die pritvate-Objekte der Klasse Logger zugreifen kann" dass genau das nicht geht?

    Hast du zum Durchsteppen im Debugger (was ich normalerweise übrigens auch "debuggen" nenne :)) auch die Optimierungen deaktiviert? Also eine "Debug Konfiguration" gebaut?

    Ja, ich habe Optimierungen deaktiviert (-O(char)0(int)) und mit der Option -g kompiliert. Mit den Private-Objekten meinte ich, dass die Funktion Logger::write() nicht auf die privaten Variablen der Logger-Klasse zugreifen kann, aber nur in den Funktionen Socket_Server::recv() (Was mein Ersatz für die Operator-Überladung zu Testzwecken ist) und Socket_Server::close() ...

    mfg D3lta



  • D3lta schrieb:

    Mit den Private-Objekten meinte ich, dass die Funktion Logger::write() nicht auf die privaten Variablen der Logger-Klasse zugreifen kann, aber nur in den Funktionen Socket_Server::recv()

    Und du glaubst dass ich es jetzt besser verstehe? 🙂
    (Ich versteh gar nix)

    Was meinst du mit "kann nicht zugreifen"?
    "Kann nicht zugreifen" heisst für mich "compiliert nicht". Wobei du das wohl nicht meinst. Aber was meinst du dann?
    ...?
    Crash beim Zugriff oder was?
    Wenn Crash beim Zugriff, dann ist vermutlich der "this" Pointer im Eimer.

    D.h. guck in die Aufrufende Funktion, dort wird der Zeiger der vor dem ->write steht kaputt sein. Oder, falls das ein Member ist, ist u.U. schon dort der "this" Zeiger kauptt, also noch eine Funktion weiter rausgehen und den "this" Zeiger kontrollieren.

    Falls du was anderes meinst: erklärs mir. Ich versteh's wirklich nicht, ich stell mich nicht doof, Ehrenwort 🙂



  • hustbaer schrieb:

    D3lta schrieb:

    Mit den Private-Objekten meinte ich, dass die Funktion Logger::write() nicht auf die privaten Variablen der Logger-Klasse zugreifen kann, aber nur in den Funktionen Socket_Server::recv()

    Und du glaubst dass ich es jetzt besser verstehe? 🙂
    (Ich versteh gar nix)

    Was meinst du mit "kann nicht zugreifen"?
    "Kann nicht zugreifen" heisst für mich "compiliert nicht". Wobei du das wohl nicht meinst. Aber was meinst du dann?
    ...?
    Crash beim Zugriff oder was?
    Wenn Crash beim Zugriff, dann ist vermutlich der "this" Pointer im Eimer.

    D.h. guck in die Aufrufende Funktion, dort wird der Zeiger der vor dem ->write steht kaputt sein. Oder, falls das ein Member ist, ist u.U. schon dort der "this" Zeiger kauptt, also noch eine Funktion weiter rausgehen und den "this" Zeiger kontrollieren.

    Falls du was anderes meinst: erklärs mir. Ich versteh's wirklich nicht, ich stell mich nicht doof, Ehrenwort 🙂

    Also: Ich habe testweise statt der privaten Objekte Logger::t_raw und Logger::time_tm temporäre Objekte in der Funktion write verwendet.
    Beim Ausführen kam dann der "Segmention fault" erst bei dem schreiben in die Datei mit fstream Logger::log, statt wie vorher schon bei den Zeitroutinen. Also kann write in einigen Fällen nicht richtig auf die privaten Objekte der Klasse Logger zugreifen.

    mfg D3lta



  • Okay, ich habe den Fehler! 💡
    Danke an alle, die versucht haben, mir zu helfen 👍
    Ohne den gdb, den ich vor diesem Thread noch nicht kannte (Ich habe also auch gut etwas gelernt 😉 ) hätte ich an die 2 Tage des Rätselns garantiert noch einige dranhängen müssen 😉
    Beim ausführlichen debuggen mit gdb ist mir aufgefallen, wo der Fehler ist: 😃
    Ich erzeuge in der main.cpp ja ein Socket_Server cli. Doch ich habe den Fehler gemacht den Zeiger Logger log nicht zu initialisieren (Schande über mich 😞 ). So zeigte dieser auf eine komplett falsche Adresse, auf die das Programm garantiert keinen Zugriff hatte. Ich habe den Fehler beseitigt, indem ich den Konstruktor Socket_Server::Socket_Server() durch Socket_Server::Socket_Server(Logger&) ersetzt habe. Und in der Main habe ich dann den Aufruf Socket_Server cli; durch Socket_Server cli(log); ersetzt. Jetzt läuft das Programm, wie es soll. 🤡

    mfg D3lta

    P.S.: Ich passe noch den Titel an, weil er eigentlich komplett falsch ist 😉


Anmelden zum Antworten