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 allesHier 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 undvoid*
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?
-
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);
-
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?!
-
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?