Zugriffsfehler auf "std::map" in " _Orphan_ptr(const _Nodeptr _Ptr)"



  • Mal ne blöde Frage, hältst du irgendwo Iteratoren auf Map Elemente und durch eine erase oder so ist die Position nicht mehr dereferenzierbar? Sowas ist mir vor nicht all zu langer Zeit mal passiert.



  • @Schlangenmensch
    Hallo Schlangenmensch,
    das ist mir zwischendurch natürlich auch passiert.
    Da stürzt es natürlich gleich ab. Gibt dann ne andere Fehlermeldung.
    Habe diverse Sachen eingebaut, um sicherzustellen, dass auch der jeweilige Thread weg ist, bevor das map-Element gelöscht wird.
    Ich setze die Iteratoren möglichst auf "end()", wenn ich sie nicht mehr brauche.
    Das Programm läuft auch schon mal übers Wochenende und sammelt dabei Daten.
    Auch kann ich Verbindungen Trennen und wieder aktivieren, wobei natürlich die zugehörigen Threads auch eliminiert werden.
    Also für die Dauer des Betriebs habe ich das alles ja hinbekommen,
    abgesehen,
    wenns bei diversen anderen Versuchen dann da auch gekracht hat.
    Nur, wenns beim beenden des Programms aus dem Destruktor des Basis-Objekts raus geht, dann krachts immer.
    Daher denke ich, dass die Destruktoren nochmals alle aufgerufen werden
    und es in der "map" eben stecken bleibt, weil die Aufruf-Schlange durch die "struct" unterbrochen wird.
    @Th69 Ja, die Datenstruktur ("struct") funktioniert ja schon lange.
    Es ist die "map" drum rum, die versagt. Aus der "struct" wird auch irgendwie der HMI Teil angesprochen ("irgendwie", ja stammt noch vom Vorgänger).
    Ich sehe daher auch meine Umbaumöglichkeiten eingeschränkt.
    @DocShoe Den cppCheck hatte ich auch schon mehrfach angedacht, bin aber bisher immer im Versuch stecken geblieben, weils dann anders auch ging.



  • Rufst du etwa irgendwo (aus dem anderen Thread heraus) explizit delete für diese map auf?
    Oder meinst du nur map.clear(), wenn du von

    ..., dass auch der jeweilige Thread weg ist, bevor das map-Element gelöscht wird.

    bzw. aus deinem Eingangsbeitrag

    Innerhalb des Threads, der die Daten in die "std::map" geschrieben hat,
    kann das map-Element auch wieder gelöscht werden, sowie auch die Daten darin bereinigt werden können.

    schreibst?

    Ansonsten mußt du uns wirklich mal den Code der betreffenden Stellen zeigen.



  • @Th69
    Ich versuche sogar alles.
    In erster Linie bereinige ich die "map"-Elemente in dem Thread, in dem ich sie reingeschrieben habe, genauer das eine Element, das dieser Thread geschrieben hat.
    Da benutze ich auch das "delete()" auf die "Objekte" (Ringspeicher) innerhalb der "map".
    In den Objekten, die ihren Thread aufrufen (zu jedem Thread gehört eins für die "open()" und "close()" Methoden z.B.), warte ich, bis explizit der Thread über ein Flag sein Ende angezeigt hat, bis ich das auch beende, versuche aber auch zusätzlich zu bereinigen.
    An solchen und auch anderen Stellen bin ich damit auch immer wieder auf die Nase gefallen, da auch diese Probleme ("_Orphan_ptr") auftraten und dann auch teils im Betrieb.
    Da habe ich auch immer wieder zu viel des Guten versucht.

    Mein Basis-ClientThread, der die ganzen Nachrichten an die aufgeschalteten ServerThreads verteilt, ist natürlich drauf angewiesen,
    dass sein Iterator auch immer auf Daten zeigt (Thread beendet und seine Daten aus "map" gelöscht).
    Sollte aber eines dieser Elemente gelöscht worden sein, ohne dass dieser das rechtzeitig merkt,
    dann steht dieser Iterator auf "end()". Der Crash zeigt dann aber auch einen anderen Grund. Und der ist dann eigentlich von der Ursache her trivial, also erklärbar.

    Aber am Ende des Anlage-Objekts kommt dann immer dieser "Orphan" Fehler.
    Da gibt es dann auch zwei Möglichkeiten:

    1. Die "maps" sind schon alle ordentlich bereinigt und leer.
      Dann kommt die eine "Orphan" Methode.
    2. Es ist noch ein Element drin, das ich im Destruktor des Anlage-Objekts, explizit und auch mit "delete()" auf die Ringspeicher, löschen möchte,
      dann kommt im "erase()" eine andere "Orphan" Methode.
      Also die Objekte in der "struct" (Ringspeicher) kann ich da sogar bereinigen.
      Nur dann das "map"-Element mit "erase()" auch noch löschen, nein.

    Habe schon alle Codefragmente hin und her geschoben.
    Teils haben sie dort dann funktioniert, teils auch nicht. Dann wieder dort raus.
    Nur das Programm beenden klappt nie!
    Und da verabschiedet es sich auch nicht mit einer Fehlermeldung und ist dann weg.
    In der Regel muss ich sogar den Taskmanager zuhilfe nehmen.



  • Du versteifst dich zu sehr auf die map und dessen Elemente.
    Du hast (höchstwahrscheinlich!) aber einen Speicherüberschreiber, der den Speicher des map-Objekts in der Anlage-Klasse korrumpiert.

    Daher noch mal der dringende Rat: benutze CppCheck oder debugge per Datenhaltepunkt (so daß möglichst direkt das Programm beendet wird ohne Elemente in die map einzufügen oder zu löschen)!!!



  • @Th69
    Mit dem cppCheck werd ich mich auf jeden Fall auseinandersetzen.
    Andererseits habe ich die Anwendung auch schon so konfiguriert,
    dass erst gar nichts mehr in die "map" geschrieben wird.
    Also so, dass in die "map" einfach nur ein NULL-Pointer geschrieben wird, statt ein Pointer auf die "struct".
    Von der "map" habe ich dann nur den Key verwendet, um sicherzustellen,
    dass ich im gewünschten Bereich bin.
    Für diesen Fall habe ich dann den ursprünglichen Pointer auf meine alte "struct" verwendet.
    Zusätzlich habe ich ausgeschlossen, dass irgendwelche ServerThreads gestartet wurden.
    Also alles, was jemals in diese eine "map" mit diesen Ringspeicher-Objekten geschrieben wurde, war dann dieser NULL-Pointer.
    Die andere "map", die eigentlich die Verwaltung der ServerThreads übernimmt, blieb dabei völlig unberührt und leer.
    Trotzdem hats beim beenden gekracht, also in der "map" mit den Ringspeicher-Objekten.

    Bin noch nicht dazugekommen, weiterzumachen, da gerade eine andere Software Probleme macht.



  • @elmut19 Ohne Code wird es mühselig.

    Vielleicht steht das schon hier im Thread aber,
    was ist denn der letzte Aufruf aus deinem Code bevor es kracht bzw. in CBaseAnlage Zeile 256? Das scheint ja der Aufruf zu sein, bei dem es kracht.
    Vielleicht mal da nen Breakpoint rein setzen und gucken was da passiert (oder schon vorher passiert ist).

    Sehe ich das Richtig, dass du die Ringspeicher manuell verwaltest? Kann es da beim Beenden der Software zu einem Double Free kommen?

    Möglicherweise kannst du den Code auf ein wirkliches Minimalbeispiel reduzieren? Alles löschen, was nicht direkt mit dem Problem zu tun hat. Ist bei größeren Projekten mühselig, aber wenn sonst nix geht, kann man so das Problem gut einkreisen.



  • @Schlangenmensch
    Der Code ist momentan noch oft doppelt gemoppelt und ähnlich wie hier auch an anderer Stelle zu finden.
    Die "maps" sind beide Member von "CBaseAnlage".
    Ich stelle das Ende der "~CBaseAnlage()" dann mal hier rein.
    Wenn eine funktionierende Variante mal da ist, kann ich auch aufräumen.

    Es tauchen hier, je nachdem, was in den Threads passiert, drei Probleme auf.

    1. Beide "maps" sind leer:
      --> Es kracht bei Ausführung der letzten "}" von "~CBaseAnlage()" und immer in der "xxRsp"-map und mit "_Orphan.."
    2. Die "m_mapSocketThreadRsps" hat noch gültige Elemente:
      --> Es kracht beim "erase()", nicht beim "delete XX->second->pWriteRsp;"
      Momentan kann ich leider keine definitive Aussage zur zweiten "map", "m_mapServerRWThreads" machen.
      Die enthält nur triviale Objekte, wie "CString".
      Ich glaube aber, die machte beim "erase()" auch diese Probleme und auch mit "_Orphan..".
      Das wäre aber wichtig für weitere Schlüsse. Müsste dazu aber diese solo haben, und das ist schwierig.
      Trotzdem könnte es daran liegen, dass die Elemente in einem Thread reingeschrieben wurden.
    3. In den "maps" sind ungültige Objekte:
      --> Wenn ein Thread "gekillt" wurde, konnte er sein "map"-Element nicht löschen.
      Dann steht in jedem Parameter Müll drin und es geht noch mehr schief.
      Aber "erase()" endet auch mit "_Orphan.."

    Wenn ich den Grund wüsste, warum es bei leeren "maps" kracht, die auch mit absoluter Sicherheit keinen anderen
    Speicher berührt haben, wäre schon sehr viel geholfen, bzw. das grundsätzliche Problem gelöst.

    	int iHelp;
    	CString csKey;
    	std::map<CString,PMRCANIDSRAM>::iterator itThreadRsps;
    	std::map<CString,PMRSOCKETSERVERTHREADALL>::iterator itRWThreads;
    _again1:
    	TRACE(_T("~BaseAnlage  ---------------------- vor #Prepare and erase() all RWThread# (size: %d) / ThreadRsp (size: %d) (if (itRWThreads not empty))\n"),
    		  m_mapServerRWThreads.size(), m_mapSocketThreadRsps.size());
    	for (itRWThreads = m_mapServerRWThreads.begin(); itRWThreads != m_mapServerRWThreads.end(); itRWThreads++) {
    		csKey = itRWThreads->first;
    		itRWThreads->second->m_psData->m_iThreadAktionSoll = SOCKETCLIENTAKTION_SOLL_ENDE;
    		itThreadRsps = m_mapSocketThreadRsps.find(csKey);
    		if ((itThreadRsps != m_mapSocketThreadRsps.end()) && (itThreadRsps->second->bInUse) &&
    			(itThreadRsps->second->bInUse >= 0) && (itThreadRsps->second->bInUse < 3)) {// 24.08.22: "bInUse<3" Erkennung ungültiger Objekte
    			EnterCriticalSection(&itRWThreads->second->m_csSocketThreadCriticalSection);
    			if ((!itRWThreads->second->m_bInUseSocketThread) && 
    				(itRWThreads->second->m_bInUseSocketThread >= 0) && (itRWThreads->second->m_bInUseSocketThread < 3)){
    				LeaveCriticalSection(&itRWThreads->second->m_csSocketThreadCriticalSection);
    				DeleteCriticalSection(&itRWThreads->second->m_csSocketThreadCriticalSection);
    				itThreadRsps->second->bInUse = FALSE;
    				delete itRWThreads->second->m_psData->pInBuf;
    				itRWThreads->second->m_psData->pInBuf = NULL;
    				itRWThreads->second->m_bInUseSocketThread = FALSE;
    
    				SetWaitableTimerSleep(itThreadRsps->second->hTimerThreadRspSleep, (LONGLONG)(0));// HP, 08.05.18: Veranlasst den Thread sofort weiterzulaufen.
    				LeaveCriticalSection(&itThreadRsps->second->m_csRspCriticalSection);
    				DeleteCriticalSection(&itThreadRsps->second->m_csRspCriticalSection);
    				if (!itThreadRsps->second->bInUse) {// 10.08.22: ergänzt. Soll vorzeitiges Ende der Anlage verhindern (bis "ClientThread" fertig)
    					itThreadRsps->second->bInUse = FALSE;
    					if (itThreadRsps->second->pErrorRsp)
    						delete itThreadRsps->second->pErrorRsp;
    					if (itThreadRsps->second->pReadRsp)
    						delete itThreadRsps->second->pReadRsp;
    					if (itThreadRsps->second->pWriteRsp)
    						delete itThreadRsps->second->pWriteRsp;
    					itThreadRsps->second->pErrorRsp = NULL;
    					itThreadRsps->second->pReadRsp = NULL;
    					itThreadRsps->second->pWriteRsp = NULL;
    					if (!itThreadRsps->second->bInUse) itThreadRsps->second->bDataInWRITE = FALSE;
    					TRACE(_T("~BaseAnlage  ---------------------- RWThread Nr:  All ThreadRsp prepared for delete\n"));
    				}
    				else {
    					DoWaitableTimerSleep0((LONGLONG)(-1000) * 200); // in 100 Nano-Sekunden --> "200" = 0,02 Sec.
    					goto _again1;
    				}
    				itRWThreads = m_mapServerRWThreads.end();
    
    				TRACE(_T("~BaseAnlage  ---------------------- RWThread Nr:  before erase\n"));
    				EnterCriticalSection(&m_csmapRWThreadsCriticalSection);
    				iHelp = m_mapServerRWThreads.erase(csKey);
    				LeaveCriticalSection(&m_csmapRWThreadsCriticalSection);
    				EnterCriticalSection(&m_csmapThreadRspsCriticalSection);
    				iHelp = m_mapSocketThreadRsps.erase(csKey);
    				LeaveCriticalSection(&m_csmapThreadRspsCriticalSection);
    				TRACE(_T("~BaseAnlage  ---------------------- RWThread Nr:  after erase\n"));
    				itRWThreads = m_mapServerRWThreads.begin();
    				goto _again1;
    			}
    			else {
    				LeaveCriticalSection(&itRWThreads->second->m_csSocketThreadCriticalSection);
    				DoWaitableTimerSleep0((LONGLONG)(-1000) * 200); // in 100 Nano-Sekunden --> 0,02 Sec.
    				goto _again1;
    			}
    		}// if ((itThreadRsps .. found
    	}// for(itRWThreads)
    _again2:
    	TRACE(_T("~BaseAnlage  ---------------------- vor  All ThreadRsp (size: %d) Data delete and NULL, no erase() (if (ThreadRsp not empty))\n"),
    		  m_mapSocketThreadRsps.size());
    	for (itThreadRsps = m_mapSocketThreadRsps.begin(); itThreadRsps != m_mapSocketThreadRsps.end(); itThreadRsps++) {
    		if ((itThreadRsps->second->bInUse >= 0) && (itThreadRsps->second->bInUse < 3)) {// Hinweis, dass Inhalt auf ungültige Daten zeigt
    			SetWaitableTimerSleep(itThreadRsps->second->hTimerThreadRspSleep, (LONGLONG)(0));// HP, 08.05.18: Veranlasst Thread sofort weiterzulaufen.
    			LeaveCriticalSection(&itThreadRsps->second->m_csRspCriticalSection);
    			DeleteCriticalSection(&itThreadRsps->second->m_csRspCriticalSection);
    			if (!itThreadRsps->second->bInUse) {// 10.08.22: ergänzt. vorzeitiges Ende der Anlage verhindern (bis "ClientThread" fertig)
    				itThreadRsps->second->bInUse = FALSE;
    				if (itThreadRsps->second->pErrorRsp)
    					delete itThreadRsps->second->pErrorRsp;
    				if (itThreadRsps->second->pReadRsp)
    					delete itThreadRsps->second->pReadRsp;
    				if (itThreadRsps->second->pWriteRsp)
    					delete itThreadRsps->second->pWriteRsp;
    				itThreadRsps->second->pErrorRsp = NULL;
    				itThreadRsps->second->pReadRsp = NULL;
    				itThreadRsps->second->pWriteRsp = NULL;
    				if (!itThreadRsps->second->bInUse) itThreadRsps->second->bDataInWRITE = FALSE;
    				TRACE(_T("~BaseAnlage  ---------------------- ThreadRsp Data set to NULL.\n"));
    			}
    			else {
    				DoWaitableTimerSleep0((LONGLONG)(-1000) * 200); // in 100 Nano-Sekunden --> "200" = 0,02 Sec.
    				goto _again2;
    			}
    		}
    	}
    	DeleteCriticalSection(&m_csSocketThreadsEndCriticalSection);
    	DeleteCriticalSection(&m_csmapRWThreadsCriticalSection);
    	DeleteCriticalSection(&m_csmapThreadRspsCriticalSection);
    	/*
    	if (m_mapSocketThreadRsps.size() > 0)
    		m_mapSocketThreadRsps.clear();
    	if (m_mapServerRWThreads.size() > 0)
    		m_mapServerRWThreads.clear();*/
    }
    
    


  • @elmut19 Das ist das Ende von dem Destruktor? Mich wundert gerade, dass überhaupt was funktioniert.

    Das ist zu viel Code, da fehlt Abstraktion und Kapselung und dann noch 2 GOTO Sprungmarken oO

    Kann es z.B. passieren, dassDeleteCriticalSection(&itThreadRsps->second->m_csRspCriticalSection);aufgerufen wird und das hinterher aufgrund von goto _again1; nochmal LeaveCriticalSection aufgerufen wird?

    Warum überhaupt erase? Die Map wird nach dem Destruktor doch eh aufgeräumt?

    Ich habe gerade erstmal gedacht, dass du immer einen Eintrag in der Map überspringst, macht du aber aufgrund des GOTO nicht, glaube ich.

    Kann dein Struct was du in m_mapServerRWThreads hältst nicht seine eigenen Ressourcen verwalten?

    Es wirkt auch komisch, dass du erst die CriticalSection verlässt und aufräumst, und dann Speicher freigibst, auf den in der Zwischenzeit ja wieder ein anderer Thread zugreifen könnte, oder?



  • Die Frage ist auch: gibt es den Crash auch, ohne den gezeigten Destruktor-Code?



  • @Th69 @Schlangenmensch
    Hallo Schlangenmensch,
    leider muss ich Dir in allen Punkten Recht geben!
    Jetzt sehe ich es auch, dass die CritSec wieder aufgerufen werden kann, obwohl sie schon weg ist. Sch....
    Über "erase()" ... Ja, muss sich eigentlich selbst verwalten. Hat mir aber auch diesen Fehler zurückgegeben.
    Und ja..., "goto" nur wegen dem überspringen.
    Aber da die CritSec ja im Element steckt, muss ich sie vor dem Aufräumen löschen.
    Und es ist und muss auch ausgeschlossen sein, dass ein neuer Thread die "map"-Elemente eines alten Threads verwendet.
    Der Key in der map ist daher die IP des entfernten Clients.
    Und dieser entfernte Client darf auch erst wieder einen Thread erzeugen, wenn sein alter Thread auch wirklich weg ist.
    Das hat auch funktioniert, bzw. funktioniert noch immer.

    Das ganze Zeug hätte auch erst gar nicht da rein gesollt.
    Ich habe das so oder ähnlich an verschiedenen Stellen reingemurkst,
    um zu sehen, ob irgendwas gegen mein Problem hilft.
    Der ganze Code sollte eigentlich nie so aussehen! Es ist ne einzige Baustelle.

    Ich hatte von Anfang an versucht, die Sachen dort aufzuräumen, wo ich sie in die "maps" reingeschrieben habe.

    Auch habe ich inzwischen aus der "struct" eine "richtige" "class" gemacht, mit ausgewiesenem Konstruktor und Destruktor.
    Das hat auch nichts geholfen, obwohl ich mich überzeugt habe, dass der Destruktor auch durchlaufen wird und dabei auch enthaltene Objekte aufräumt..

    @Th69 Und hier auch Ja!
    Es passiert auch, wenn dieser Code gar nicht durchlaufen wird, also die "maps" schon leer sind!
    Es passiert aber auch nur, wenn einmal etwas in die "map" geschrieben wurde.
    Dazu habe ich, neben den Server-Threads, auch mal den Basis-Client-Thread abgeklemmt.
    Es wurde also auch dieses NULL-Element nicht in die map geschrieben.
    Da machten die "maps" keine Probleme.
    Aus der anderen "map" (m_mapServerRWThreads) konnte ich an der Stelle Elemente löschen.

    Aber zu dem Ganzem ist mir noch etwas eingefallen.
    Wie verhält es sich mit dem tatsächlichen Ende eines Threads?
    Bisher warte ich dieses Ende (noch) nicht über "WaitForSingleObject" oder "..Multiple.." ab. Bisher war das unkritisch.
    Und wenn ich mir die Thread-Liste ansehe, so sind da noch Fragmente einiger weniger Threads drin, wie z.B. "ntdll!TppWorkerThread",
    die aus der Threadverwaltung von Windows stammen.
    Aber ich weiss nicht, woher die kommen.
    Sollten sie noch einen Teil meiner besagten Threads enthalten, so könnte dadurch evtl. der Speicher noch blockiert sein.

    Ich werde auf jeden Fall die Event-Abfrage auf das Ende der Threads einbauen!

    Und im Übrigen nochmals VIELEN DANK an alle für Eure Hilfe.



  • @Th69
    Habe das mit dem "WaitForSingleObject" nun probiert.
    Zuvor hatte ich ja auch genug Wartezeit eingeplant (5 Sekunden).
    Nun gehts wesentlich schneller. Ist eigentlich auch der korrekte Weg!
    Leider ist das Resultat immer noch dasselbe.
    Die "maps" sind leer, und es crasht trotzdem.



  • Ok, erstmal, wenn du mit erase die Maps selbst leeren willst, weil du unter umständen einen Eintrag (noch) nicht löschen möchtest, das ginge auch mit einer Schleife ohne goto 😉

     //map m
     auto iter = m.begin();
     while(iter != m.end())
     {
        if(/*erase case*/)
        {
           m.erase(iter->first);
           iter = m.begin();
        }
        else
        {
           //what ever
        }
     }
    

    Du darft DeleteCriticalSection erst aufrufen, wenn die CriticalSection nicht mehr benötigt wird. Also, auch, wenn kein Thread die mehr benötigt.
    Wenn du auf mehrere Threads verteilt gemeinsam benötigte Ressourcen hast, muss du erst dafür sorgen, dass diese die Ressourcen nicht mehr benötigen, also warten bis die Threads alles soweit abgearbeitet haben, oder beendet worden sind.

    Was ist denn der Rückgabewert von WaitForSingleObject? Und schickst du das Signal auch wirklich am Ende des Threads?



  • @Schlangenmensch sagte in Zugriffsfehler auf "std::map" in " _Orphan_ptr(const _Nodeptr _Ptr)":

    Ok, erstmal, wenn du mit erase die Maps selbst leeren willst, weil du unter umständen einen Eintrag (noch) nicht löschen möchtest, das ginge auch mit einer Schleife ohne goto 😉

     //map m
     auto iter = m.begin();
     while(iter != m.end())
     {
        if(/*erase case*/)
        {
           m.erase(iter->first);
           iter = m.begin();
        }
        else
        {
           //what ever
        }
     }
    

    Mit C++11 liefert std::map::erase() einen iterator auf das nächste Element oder auf std::map::end()



  • @Schlangenmensch
    Vielen Dank für den Code-Schnipsel. Is wesentlich besser als meiner!

    Das "WaitForSingleObject" gibt "0" zurück.
    Es wird sogar (versehentlich) zweimal durchlaufen.
    Beim ersten Mal sieht man auch die TRACES, die das Thread-Ende anzeigen.
    Und man kann die Zeit ablesen die zum Durchlaufen des "WaitFor.." gebraucht wurde.
    Beim zweiten Mal gibts dann keine Zeitdifferenz. Thread ist ja weg.
    Sieht also so aus, als würde es funktionieren.

    @firefly Und ja, ich verwende noch C++11. Bin wohl in der falschen Doku gelandet.
    ... Oh nee, doch nicht. Bei Key-basiertem "erase()" wird ein "size_type" zurückgegeben.
    Aber davon abgesehen:
    Es kommen ja zwei "erase()" hintereinander.
    Und es kracht erst beim zweiten ("Rsp"-map), wenns da durch geht.
    Durch die "if"-Abfrage ist ja gewährleistet, dass in beiden "maps" was drin steht.

    Ansonsten krachts immernoch, wenn die maps leer sind, und das auch immer bei der "..Rsp"-map.



  • Hmm dann wird es wohl ohne Beispiel code, welcher das Problem nachstellt, schwer dir zu helfen



  • @firefly Huch, danke. Hätte ich noch mal nachlesen sollen, hab ich so nämlich noch nicht wirklich gebraucht.

    Aber, den nächsten Iterator gibt es nur, wenn man erase den Iterator übergibt, ich habe ja geschlafen und den Key übergeben, dann wird die Anzahl gelöschter Elemente zurück gegeben, wie @elmut19 richtig angemerkt hat.

    @elmut19 wenn nix hilft, dann alles an Code entfernen, dass nicht mit dem Problem zu tun hat und langsam einem Minimalbeispiel annähern. Zwischendurch immer mal überprüfen ob das Problem noch besteht. Dann kommst du vlt auch zu einem Beispiel, dass du hier teilen kannst.



  • @Schlangenmensch
    Jedenfalls vielen vielen Dank an Euch alle.
    Mal sehn, was mir noch an möglichen Änderungen einfällt.
    Ich werds dann hier reinschreiben.
    Vielleicht stimmt was nicht mit der Zugriffshierarchie auf die Objektkette.
    Grundsätzlich muss das ja funktionieren.

    Hab versucht, den CppCheck zu installieren (Version für VS 2022).
    Der mag mein VS2019 nicht. Ausgewiesenes Release für VS2019 hab ich nicht gefunden.
    Cppcheck hinterlässt schon mal einen sehr schlechten Eindruck --> gestorben!

    Habe gerade auch festgestellt, dass sich die Elemente der "Rsp"-map nur innerhalb des Threads löschen lassen, wo ich sie reingeschrieben habe.
    Selbst in dem Thread, der die einzelnen ServerThreads erzeugt, kann ich da kein Element löschen --> selber Fehler ("_Orphan...").
    Für die "RW"-map funktioniert das aber und zwar bis zum Destruktor der "BaseAnlage" hinunter.
    Die Inhalte beider maps sind Member derselben Klasse (Basis-Klasse, "CMrSocketThread"). Die "maps" sind Member der "BaseAnlage" und als Verweis (m_pmapSocketThreadRsps) in der Unterklassen von CMrSocketThread.
    Von dieser Basis-Klasse sind der TCP-ClientThread und die TCP-ServerThreads abgeleitet, respektive natürlich die Klassen,
    über die diese Threads verwaltet (Start(), Stop(), ..) werden.
    Die Ringspeicher im Inhalt der "Rsp"-map werden auch irgendwie noch initialisiert und auch individuell erzeugt.
    Aber ich kann diesen Inhalt, als "RspMap->second->Ringspeicher.irgendwas()" überall,
    innerhalb meines "Anlage"-Objekts bearbeiten und auch "delete" drauf ausführen.
    Aber ich kann an selber Stelle kein "erase()" auf dieses map-Element ausführen.
    Daher meine Annahme, dass es sich um eine spezielle Eigenschaft der "std::map" handelt, die hier versagt.

    Das mit dem "erase()" am geeigneten Ort, lässt sich ja hinbekommen.
    Aber das beim Beenden meiner Anwendung, selbst wenn die "map" leer ist, ist schon zum Verzweifeln.



  • Habe es inzwischen mit einer eigenen Linked List probiert.
    Hier gibts leider ähnliche Fehler.
    Ein "delete" auf ein Element ergibt Heap-Fehler. (Habs auch mit "delete[]" probiert.)
    Und wenn ich auf die "deletes" verzichte (Ich mache ja jeweils ein explizites "delete" auf jeden einzelnen dieser Ringspeicher, welches auch funktioniert, jedenfalls ohne Absturz!),
    so kann ich zwar die debug-Version beenden, die Release-Version bleibt aber hängen.

    // Ich verwende nun eigene Linked List! "itThreadRsps" ist Element dieser Linked List
    delete itThreadRsps->pMrThreadRsp->pWriteRsp; // keine Probleme
    delete itThreadRsps->pMrThreadRsp; // Heap-Fehler, wenn auskommentiert -> Deadlock beim Beenden
    // Wenn ich das Eine mache, muss ich natürlich das Andere jeweils auskommentieren,
    // da das Erste ja im Zweiten enthalten ist.
    

    Es scheint wohl an diesem ominösen Ringspeicher zu liegen,
    den mein Vorgänger geschrieben hat und in dem ich mich leider
    überhaupt nicht auskenne. Bisher hat der ja, ohne "map", etc. funktioniert.



  • @elmut19 sagte in Zugriffsfehler auf "std::map" in " _Orphan_ptr(const _Nodeptr _Ptr)":

    Habe es inzwischen mit einer eigenen Linked List probiert.
    Hier gibts leider ähnliche Fehler.

    Wer hätte das gedacht! (sorry, klingt jetzt blöd, aber dir wurde gesagt, dass es nicht dem Container std::map liegt)


Anmelden zum Antworten