Memleaks trotz Smartpointern in parallelem Programm?



  • Hi zusammen, ich hänge gerade an einem etwas ekelhaften Problem - wie man schon am Titel erkennen kann.

    Folgende Situation: Ich teste meinen Code mit Boost.Test, aktuell bin ich dabei, die TCP-Schnittstelle für meine Client-Server-Kommunikation zu implementieren mit Boost.Asio. Alle Speicheranforderungen geschehen mit make_shared, sollte also keine Leaks geben.
    In einem der Testfälle erstelle ich sowohl ein clientseitiges als auch ein serverseitiges Communicator-Objekt. Beide arbeiten auf unterschiedlichen asio::io_service Objekten, deren run()-Methode jeweils in einem eigenen Thread ausgeführt wird. Ich habe also den Haupt-Thread sowie die beiden ioService-Threads. Der Debugger zeigt noch einen zusätzlichen Thread an, ich vermute, dass asio oder Windows den unter der Haube für die Kommunikation via TCP anlegt.

    Mein Testfall läuft problemlos durch, Boost.Test meldet aber im Anschluss immer 31 Memleaks. Immer die selbe Größe, aber unterschiedliche Adressen. Die Inhalte sind oft selbst Adressen, unterscheiden sich also meist entsprechend (aber meist nur in 1 byte). Die Reihenfolge der Allokation der 31 Blöcke scheint auch immer die gleiche zu sein, sieht man daran, dass die Muster der Inhalte sich immer ähneln. Boost.Test gibt netterweise auch immer mit an, die wievielte Allokation der jeweilige Block war, da gibts kleine Unterschiede, wie viele Allokationen vor dem Schlamassel stattgefunden haben.

    Das merkwürdigste ist aber folgendes:
    Ich habe mehrere *_test.lib für meine Komponenten, die ich am Ende zur unittest.exe zusammenlinke. Wenn ich eine bestimmte lib neu baue, linke und die Tests laufen lasse, kommen die Leaks. Baue ich eine andere lib neu (unter anderem auch die mit dem fraglichen Testfall), linke und lasse die Tests laufen, kriege ich keine Leaks.

    Hat jemand schonmal sowas gesehen und Tips, wonach ich suchen muss?



  • Ganz bloede Frage: werden alle Threads korrekt beendet?
    zB mit einem Process Explorer checken oder so.


  • Mod

    Ist es mit deinen Entwicklungswerkzeugen möglich, die verursachende Speicherreservierung zu finden?



  • Shade Of Mine schrieb:

    Ganz bloede Frage: werden alle Threads korrekt beendet?
    zB mit einem Process Explorer checken oder so.

    Danke, das wars. Der eine Thread joint auf sich selbst, das kann nicht gut gehn *kopf->tisch*

    Folgendes Szenario: Das eine Objekt enthält seinen eigenen IoService-Thread, im Dtor joint es darauf. Das Objekt wird die meiste Zeit von einem einzigen shared_ptr gehalten, und zwar im main-Thread, wo es auch erzeugt und der IoService-Thread gestartet wird. Es schickt über async_*-Aufrufe Handler an den Service, die weak_ptr auf das Objekt enthalten. Beim Ausführen der Handler wird der weak_ptr gelockt, also ein zweiter shared_ptr erzeugt. Wenn genau dann der shared_ptr im main-Thread gekillt wird, wird beim Freigeben des shared_ptr im IoService-Thread der join dort aufgerufen und nicht im Main-Thread. Gnarf.

    Jetzt muss ich nurnoch dafür ne Lösung finden...



  • SeppJ schrieb:

    Ist es mit deinen Entwicklungswerkzeugen möglich, die verursachende Speicherreservierung zu finden?

    Jein... Ich hätte sie vermutlich mit einem Brechpunktzähler abzählen können - ich hab aber zur Übersicht erstmal nur einen BP in new(size_t) gesetzt und zwei von den Allokationen mit charakteristischen Größen gesucht. Ich wusste damit in etwa, was da noch rumhing, aber nicht wieso...


Anmelden zum Antworten