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



  • theta schrieb:

    Bei mir ist der Buffer aber 1024 Zeichen groß, da passen die paar Zeichen doch Sicher hinein, oder?

    Ja, sie passen potentiell rein. Das heisst noch lange nicht dass der recv(..) Aufruf soviele reinschreibt. Wieviel genau reingeschrieben werden sagt dir der Return Wert von recv(..). Achtung: Auch Fehler oder Connection Ende (wie schon in deinem Code behandelt) wird über den Return Code mitgeteilt.

    P.S.: Außerdem liegt der Fehler noch vor dem Aufruf von recv() !

    Wo?

    D3lta schrieb:

    ...

    P.S.: Ich habe herausgefunden, dass der Fehler zwischen dem Annehmen des Clients (was erfolgreich zu verlaufen scheint) und dem ersten Befehl in dem überladenem operator>> liegt (also eventuell ein Syntaxfehler beim operator?

    314159265358979 schrieb:

    Ich vermute mal, dass du in deinen anderen Klassen, wie hier auch, die Return-Codes nicht prüfst. Alle Socket-Funktionen geben -1 zurück, wenn etwas nicht geklappt hat. Ich würde das überprüfen und im Fehlerfall eine Exception mit aussagekräftiger Nachricht werfen - Dann siehst du sofort, wo es kracht.

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

    mfg D3lta



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



  • 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 🙂


Anmelden zum Antworten