Merkwürdiger Speicherzugriffsfehler



  • Hallo,

    ich habe einen Speicherzugriffsfehler, bin allerdings ratlos warum 🙂

    Vermutlich ist das wieder so eine simple Sache, worauf ich als Anfänger nicht komme.

    TelemetryReceiver::TelemetryReceiver(ComputeCaptureFrame computeCaptureFrame, void *cRDFParams)
    {
    	// Capture-Funktion merken
    	_computeCaptureFrame = computeCaptureFrame;
    	_cRDFParams = cRDFParams;
    
            CaptureFrameFunction();
    }
    
    void TelemetryReceiver::CaptureFrameFunction()
    {
            // Hier tritt der Speicherzugriffsfehler auf
    	_computeCaptureFrame(_cRDFParams);
    
    }
    

    Wenn diese Zeile:
    _computeCaptureFrame(_cRDFParams);
    allerdings in den Konstruktor schreibe, funktioniert alles 😮

    Hier noch der Header:

    class TelemetryReceiver
    	{
    		// Definiert die Funktion, die die Frames aufnimmt
    		typedef std::vector<unsigned char> (* ComputeCaptureFrame)(void *);
    
    		private:
    
    			struct sockaddr_in;
    
    			// Nimmt ein Frame auf
    			ComputeCaptureFrame _computeCaptureFrame;
    
    			// Objekt der Manager Klasse
    			void *_cRDFParams;
    
    			unsigned short _port;
    
    			// TCP Daten verarbeiten
    			void ComputeTCPServerData(BYTE *data, int dataLength, int clientID);
    
    			// Neuer Client verbunden	
    			void onClientConnect(int clientID);
    
    			void CaptureFrameThread();
    
    			// Liste mit ClientIDs
    			std::map<int, UDPClient> UDPClientList;
    
    		public:
    			// Konstruktor
    			TelemetryReceiver(ComputeCaptureFrame computeCaptureFrame, void *cRDFParams);
    

    Ich hoffe jemand kann mir sagen, woran das liegt 🙂

    Edit:// Mir fällt auf, dass dieser Speicherzugriffsfehler auch im Header entsteht, wenn man die Funktion unter ComputeTCPServerData schreibt.

    Habs nich etwas genauer:

    void TelemetryReceiver::ComputeTCPServerData(BYTE *data, int dataLength, int clientID)
    {
    
    	// Wert in Map?
    	if(UDPClientList.find(clientID) == UDPClientList.end())
    		throw THOMASException("Die Client ID konnte nicht gefunden werden");
    
    	switch(data[0])
    	{
    		// HeaderDaten
    		case 1: {
    
    			UDPClientList[clientID].CreateUDPClient(4222, "127.0.0.1");
                            // Wenn es hier steht gibts ein Speicherzugriffsfehler
    			CaptureFrameThread();
    			break;
    		}
    	}
    
    }
    

    ERLEDIGT: War ein Pointer Problem, trotzdem danke 🙂



  • Dir sollte selber klar sein, dass mit den paar Zeilen eine Diagnose unmöglich ist.
    Wahrscheinlich existiert das, worauf cRDFParams zeigt, nicht mehr.

    Aber die falsch deklarierte struct sockaddr_in aus deinem anderen Post kann man sehr schön sehen.



  • @manni66

    Wie muss die denn richtig? 🙂



  • Waishon schrieb:

    @manni66

    Wie muss die denn richtig? 🙂

    Nathan schrieb:
    https://www.c-plusplus.net/forum/p2443893#2443893



  • Ok danke werde ich ändern, allerdings bin gerade etwas deprimiert, da ich jetzt einen neuen Speicherzugriffsfehler erhalte im Zusammenhand mit

    *** Error in `./udp': malloc(): memory corruption: 0x00000000025c49c0 ***
    Abgebrochen (Speicherabzug geschrieben)
    

    Dies passiert, sobald ich
    std::vector<int> param = std::vector<int>(2);
    in den oben genannten Header schreibe.

    Dann gibt es den Fehler nach diesem Code:

    // Wenn Client connected TODO: In TCPServer-Klasse implementieren
    void TelemetryReceiver::onClientConnect(int clientID)
    {
    
    	// Client in map speichern
    	UDPClient *client = new UDPClient();
    	UDPClientList.insert(std::make_pair(clientID, *client));
    
    }
    

    Wenn ich es den vector, allerdings wieder heraus lösche bzw. lokal definiere klappt es.
    Dies passiert bei jedem neuen Pointer.

    Ist bestimmt so ein dummer Anfängerfehler

    Jetzt weiß ich warum die Speicherverwaltung in C++ als schwer angesehen wird 🙂

    Hier die Auaswertung mit valgrid http://pastebin.com/HYfta8PS



  • Ja Mensch...warum machst Du es Dir denn auch so schwer?!
    C++ ist kein Java!
    new/delete und void* schreien nach Problemen.

    void TelemetryReceiver::onClientConnect(int clientID)
    {
        // Client in map speichern
        UDPClientList[clientID] = UDPCLient();  
    }
    


  • @Furble Wurble

    Ja für einen Java Umsteiger ist das schon schwer 🙂 Muss ich mir merken, dass das so einfach geht.

    In meinem C++ Buch (Der C++ Programmierer) stand es mit insert und make_pair. Deswegen hatte ich es so gemacht 🙂

    Gibt es alternativen zu *void?


  • Mod

    Waishon schrieb:

    Gibt es alternativen zu *void?

    Ja. Je nach Zusammenhang sind die beste Alternative meistens Templates. Manchmal aber auch anderes. Aber void* sind typisch für C und kommen in C++ so gut wie nie vor.



  • Ok werde ich mir mal durchlesen 🙂

    Wie würde das denn in diesem Beispiel aussehen, dass ich mir darunter etwas vorstellen kann

    So?

    template<typename T>
    TelemetryReceiver(ComputeCaptureFrame computeCaptureFrame, T *cRDFParams);
    

  • Mod

    Möglicherweise. Ich werd aus deinem Eingangbeitrag nicht so ganz schlau, was hier überhaupt genau passieren soll. Was mich jedenfalls auf den ersten Blick wundert, ist der Zeiger. Ich kann mir kaum vorstellen, dass hier nicht eine Referenz oder eine Kopie besser wären.



  • Du meinst?

    void *cRDFParams

    Das hatte ich so aus dem Code von meinem Vorgänger, ich kann es ja mal anders versuchen 🙂



  • Nein!

    Entweder als Referenz

    T & cRDFParams // evtl. zusätzlich noch const
    

    oder als Kopie

    T cRDFParams
    

    Bei Templates würde ich aber generell eher zu Referenzen raten (da eine Kopie, je nach Typgröße, recht teuer sein kann - insb. wenn noch selbsterstellte Kopierkonstruktoren dazukommen)!



  • Vielen Dank für die Antworten.

    Ich hätte noch eine Frage zum new Parameter:

    Aktuell instanziere ich eine Klasse so:

    Header

    TelemetryReceiver *_teleRecv;
    

    File

    _teleRecv = new TelemetryReceiver();
    

    Wie kann ich das ohne new lösen, da es ja böse ist 🙂

    Außerdem habe ich hier noch einen Thread:
    Wie kann ich t in den Header speichern und dann den neuen Thread zuweisen ohne new?

    std::thread t(&TelemetryReceiver::CaptureFrameThread, this);
    t.join();
    


  • Einfach den Stern * weglassen und dich an Memorymanagement vom feinsten erfreuen.

    Edit: wenn es natürlich garnicht ohne pointer geht:

    shared_ptr<TelemetryReceiver> __teleRecv;
    

    und

    __teleRecv = make_shared<TelemetryReceiver>();
    


  • Das new darf aber bestehen bleiben? 😮

    Ok habs geht ohne danke 🙂

    bzw wie geht das bei den Threads?



  • Nein, natürlich nicht?!


  • Mod

    Waishon schrieb:

    bzw wie geht das bei den Threads?

    Wie geht was bei welchen Threads?



  • tkausl schrieb:

    Einfach den Stern * weglassen und dich an Memorymanagement vom feinsten erfreuen.

    Edit: wenn es natürlich garnicht ohne pointer geht:

    shared_ptr<TelemetryReceiver> __teleRecv;
    

    und

    __teleRecv = make_shared<TelemetryReceiver>();
    

    Der erste Instinkt ist unique_ptr. shared_ptr darf man nur mit gutem Grund verwenden. __teleRecv ist übrigens kein guter Variablenname (da reserviert).



  • So ich habe ein neues Problem, auch mal wieder mit Speicherzugriffsfehler:

    Es geht um felgenden Code:

    // Joystick-Daten sperren
    			_joystickMutex->lock();
    			{
    				// Achswerte kopieren
    				memcpy(_joystickAxis, &data[1], sizeof(short) * _joystickAxisCount);
    
    				// Buttonwerte kopieren
    				memcpy(_joystickButtons, &data[1 + sizeof(short) * _joystickAxisCount], sizeof(BYTE) * _joystickButtonCount);
    			}
    			_joystickMutex->unlock();
    

    Dieser Teil, ist ein Teil einer Empfangsmethode eines TCPServers.
    Wenn ich jedes Byte einzeln mit entsprechenden Abstand sende, klappt alles wunderbar. Auch die ersten paar Bytes, die unmittelbar nacheinander gesendet werden. Sobald man allerdings kurz wartet, kommt der gennante Speicherzugriffsfehler. Am Mutex liegt es nicht, da dieser Fehler auch entsteht, wenn dieser komplett auskommentiert ist.
    Ich denke es liegt an memcpy. Irgendeiner eine Idee?
    Es liegt am 2. memcpy. Wenn dieser auskommentiert ist klappt es
    Dieser Fehler tritt erst auf, seitdem ich eine neue Klasse hinzugefügt habe



  • Gibts nen Grund warum du bei &data[1] anfängst?


Log in to reply