Ram problem - Speicher freigeben



  • Ahoi,

    ich sitze vor einem relativ großen programm.
    Im Programm wird eine Datei eingelesen, verarbeitet und wieder aus geschrieben.
    Es gibt eine Datencontainer Klasse, die Daten speichert.

    Das Problem ist, dass sich das Programm irgendwo künstlich "aufbläht". Es wird nicht benutzer Speicher nicht wieder frei gegeben.

    Ich bin schon mehrmals Grob durch das Programm und habe schon einiges behoben, nicht alles gefunden.

    Desshalb meine Frage, gibt es eine art tool mit dem man den Speicherverbrauch genauer anzeigen kann?
    Ich dachte da an so eine art Ausgabe die mir immer zu speziellen Zeiten im Programm ausgibt, wie Groß eine Klasse oder darin verwendete vektoren sind.
    Wenn es ne Funktion gibt die mir die größe einer Klasse anzeigen kann, könnte ich da auch selber was basteln...

    Bin über jeden Ratschlag oder andere Tips dankbar

    Gruß
    Tim



  • Du hast einen "Memory Leak".
    Was du suchst, ist ein "Profiler".



  • Wenn es darum geht Speicherlecks zu finden, würde ich Valgrind empfehlen.



  • Unter Windows kann ich den Visual Leak Detector empfehlen.



  • Präventivschläge gegen solche Fehler führen:
    vectoren statt rohe Zeiger/Arrays nutzen.
    Smart-Pointer statt rohe Zeiger

    Und für den Fall, dass du zyklische Abhängigkeiten mit shared_pointern hast, die sollten halbwegs gut zu finden sein, denn du kannst den Fehler gut eingrenzen indem du beteiligte Klassen anguckst (eventuell auch die Architektur visualisierst, geht unter VS2012 super gut) und danach weak_ptr einsetzt.



  • stichwort schrieb:

    Du hast einen "Memory Leak".
    Was du suchst, ist ein "Profiler".

    Ein Profiler ist etwas mit dem man Performance-Probleme analysiert.
    Leaks findet man damit nicht.

    Stichworte wären eher Application-Verifier oder Leak-Detector.



  • Ahoi,

    erst mal danke für die viele Tipps 🙂

    vectoren statt rohe Zeiger/Arrays nutzen.

    es werden eigentlich nur vekotren oder vektoren von vektoren benutzt. ich möchte halt die großen vektoren finden die sich im Programm "versteckt" haben.

    Unter Windows kann ich den Visual Leak Detector empfehlen.

    ich programmiere unter Suse und werd mal schaun was es da für Programme gibt. oder kennt ihr ein gutes?



  • Nötigenfalls reicht es auch, wenn du die Operatoren "new" und "delete" überlädst und mitzählst. Da gibt es garantiert was im Internet.



  • ich hab das Programm valgrind jetzt mal heruntergeladen und so ausgeführt:

    valgrind --tool=memcheck ./Mesh2HOMAT /home/tim/workspace2/beispiele/dendriten/ascii_dendrit_frac.vtk
    

    Ich hab mal das raus kopiert was valgrind "berichtet" hat:

    ==4251== Memcheck, a memory error detector.
    ==4251== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
    ==4251== Using LibVEX rev 1854, a library for dynamic binary translation.
    ==4251== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
    ==4251== Using valgrind-3.3.1, a dynamic binary instrumentation framework.
    ==4251== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
    ==4251== For more details, rerun with: -v
    ==4251==
    ==4251== Conditional jump or move depends on uninitialised value(s)
    ==4251==    at 0x467B49: vtk_input::readStructuredPts(std::basic_ifstream<char, std::char_traits<char> >&, global_vars*) (in /home/tim/workspace2/mesh2homat/Mesh2HOMAT)
    ==4251==    by 0x4700AE: vtk_input::readVtk(global_vars*) (in /home/tim/workspace2/mesh2homat/Mesh2HOMAT)
    ==4251==    by 0x43995C: main (in /home/tim/workspace2/mesh2homat/Mesh2HOMAT)
    
    ==4251==
    ==4251== Conditional jump or move depends on uninitialised value(s)
    ==4251==    at 0x439987: main (in /home/tim/workspace2/mesh2homat/Mesh2HOMAT)
    
    ==4251==
    ==4251== Conditional jump or move depends on uninitialised value(s)
    ==4251==    at 0x416E88: app_core::MaterialAnalyser(global_vars*) (in /home/tim/workspace2/mesh2homat/Mesh2HOMAT)
    ==4251==    by 0x4399F4: main (in /home/tim/workspace2/mesh2homat/Mesh2HOMAT)
    
    ==4251== Warning: set address range perms: large range 100663296 (undefined)
    ==4251== Warning: set address range perms: large range 100663296 (undefined)
    ==4251== Warning: set address range perms: large range 201326592 (undefined)
    ==4251== Warning: set address range perms: large range 100663328 (noaccess)
    ==4251== Warning: set address range perms: large range 201326592 (undefined)
    ==4251== Warning: set address range perms: large range 100663328 (noaccess)
    
    ==4251== Warning: set address range perms: large range 180000000 (undefined)
    ==4251==
        Valgrind's memory management: out of memory:
           newSuperblock's request for 4194304 bytes failed.
           5012922368 bytes have already been allocated.
        Valgrind cannot continue.  Sorry.
    
        There are several possible reasons for this.
        - You have some kind of memory limit in place.  Look at the
          output of 'ulimit -a'.  Is there a limit on the size of
          virtual memory or address space?
        - You have run out of swap space.
        - Valgrind has a bug.  If you think this is the case or you are
        not sure, please let us know and we'll try to fix it.
        Please note that programs can take substantially more memory than
        normal when running under Valgrind tools, eg. up to twice or
        more, depending on the tool.  On a 64-bit machine, Valgrind
        should be able to make use of up 32GB memory.  On a 32-bit
        machine, Valgrind should be able to use all the memory available
        to a single process, up to 4GB if that's how you have your
        kernel configured.  Most 32-bit Linux setups allow a maximum of
        3GB per process.
    .
        Whatever the reason, Valgrind cannot continue.  Sorry.
    

    Allerdings verstehe ich nicht so richtig was mir die ganzen ausgaben jetzt sagen sollen. ich benutze auf jeden fall 64bit..


  • Mod

    Der erste Fehler ist wie immer der wichtigste. Alles danach könnten Folgefehler sein, insbesondere da du hier offensichtlich undefiniertes Verhalten erzeugst.

    Mach folgendes:
    1. Compilier dein Programm mit Debugsymbolen und Vorzugsweise auch noch ohne Optimierungen.
    2. Mehr valgrind-Tools anschalten. Normaler Lauf, um Fehler zu finden:

    valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes dein_programm
    

    Da du schon weißt, das hier ein Fehler vorliegt, machst du (Achtung: Sehr langsam!):

    valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes --track-origins=yes dein_programm
    

    Damit werden dir auch Hinweise über die Ursache des Fehler gegeben.

    Zu 32/64: Du hast ja schon 5 GB allokiert. Was größer ist, als in den meisten 32-Bit Kerneln per Default erlaubt ist. Ist deinem Rechner vielleicht einfach der physikalische Speicher ausgegangen? Klingt so, als hätte dein Rechner <=8 GB Speicher. Passt das?
    Soll dein Programm derart viel Speicher brauchen? 5 GB kommt zwar manchmal vor, aber ist immer noch ungewöhnlich genug, dass ich mal lieber nachfrage.



  • Der erste Fehler ist wie immer der wichtigste. Alles danach könnten Folgefehler sein,

    warnings sind für mich nicht unbedingt fehler oder wo beginnt für dich der erste fehler?

    1. Compilier dein Programm mit Debugsymbolen und Vorzugsweise auch noch ohne Optimierungen.

    was sind debugsymbole? meinst du damit eine debugversion erstellen?

    Soll dein Programm derart viel Speicher brauchen? 5 GB kommt zwar manchmal vor, aber ist immer noch ungewöhnlich genug, dass ich mal lieber nachfrage.

    Genau darum geht es.

    ich hab hier 4gb aufem laptop. aber ohne valgrind läuft das programm durch.(langsam)

    eigentlich sollte das Programm nicht so groß werden. bzw es muss nicht so groß werden. Irgendwo werden unnötig daten zwischen gespeichert und ich will herausfinden wo.


  • Mod

    Warnungen sind immer Fehler. Nichtsdestotrotz liegt hier doch ohnehin keine Warnung vor, sondern ein handfester und ernster Fehler:

    ==4251== Conditional jump or move depends on uninitialised value(s)
    ==4251==    at 0x467B49: vtk_input::readStructuredPts(std::basic_ifstream<char, std::char_traits<char> >&, global_vars*) (in /home/tim/workspace2/mesh2homat/Mesh2HOMAT)
    ==4251==    by 0x4700AE: vtk_input::readVtk(global_vars*) (in /home/tim/workspace2/mesh2homat/Mesh2HOMAT)
    ==4251==    by 0x43995C: main (in /home/tim/workspace2/mesh2homat/Mesh2HOMAT)
    

    was sind debugsymbole?

    Google: was sind debugsymbole

    Ich rate mal, dass du GCC als Compiler benutzt. Benutz den Schalter -g oder einen seiner Verwandten.



  • Evtl. hilft Dir auch massif/ms_print

    Aber zuvorderst würde ich mich auch um die Warnungen kümmern, die Du bis jetzt schon bekommen hast.



  • Google: was sind debugsymbole

    hatte ich schon gemacht, konnte ich mir nichts drunter vorstellen.

    "Informationen die aus dem Quelltext genommen werden(zb. variablennamen)"

    Conditional jump or move depends on uninitialised value(s)

    at 0x467B49: vtk_input::readStructuredPts

    irgend ne bewegung abhängig von nicht initialisierten werten beim einlesen.
    super fehler meldung.

    valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes dein_programm

    hatte die gleiche ausgabe wie der erste befehlt



  • [quote="Rustyspoon"]

    Der erste Fehler ist wie immer der wichtigste. Alles
    ich hab hier 4gb aufem laptop. aber ohne valgrind läuft das programm durch.(langsam)

    Das ist durchaus verständlich, da valgrind auch einiges an speicher benötigt.

    Rustyspoon schrieb:

    eigentlich sollte das Programm nicht so groß werden. bzw es muss nicht so groß werden. Irgendwo werden unnötig daten zwischen gespeichert und ich will herausfinden wo.

    Sollte es sich dabei nicht um ein Speicherleck handeln (Speicher der nicht mehr benutzt wird, wird nicht freigegeben) sondern darum, dass die Vorgehensweise einfach zu Speicherhungrig ist, hilft dir Valgrind nicht. Dann muss man sich das Programm mal im ganzen anschauen. Versuch aber erst mal die Fehler weg zubekommen, die Valgrind anzeigt.


  • Mod

    hatte ich schon gemacht, konnte ich mir nichts drunter vorstellen.

    "Informationen die aus dem Quelltext genommen werden(zb. variablennamen)"

    Dann lies weiter, schlag Begriffe nach, die du nicht verstehst, lies andere Links, mach selbstständig Googlefragen zu den Dingen, die du nicht verstehst.

    Rustyspoon schrieb:

    Conditional jump or move depends on uninitialised value(s)

    at 0x467B49: vtk_input::readStructuredPts

    irgend ne bewegung abhängig von nicht initialisierten werten beim einlesen.
    super fehler meldung.

    Was verstehst du da dran nicht? Schrillen denn nicht schon allein bei "nicht initialisiert" alle Alarmglocken?

    Rustyspoon schrieb:

    valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes dein_programm

    hatte die gleiche ausgabe wie der erste befehlt

    Wenn du meine Antworten, Fehlermeldungen und Wikipedia derart unaufmerksam und unmotiviert liest, dann ist ja klar, dass das nichts wird. Wir alle wollen dir gerne was erklären. Dies setzt aber den Willen zum Verstehen deinerseits voraus. Verstehen ist Arbeit. Verstehen braucht oftmals auch mehr als bloß ein paar Sätze zu überfliegen:

    SeppJ schrieb:

    lies weiter, schlag Begriffe nach, die du nicht verstehst, lies andere Links, mach selbstständig Googlefragen zu den Dingen, die du nicht verstehst.

    Unmittelbar hatte ich oben übrigens folgendes zu valgrind gesagt:

    SeppJ schrieb:

    Normaler Lauf, um Fehler zu finden:

    valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes dein_programm
    

    Da du schon weißt, das hier ein Fehler vorliegt, machst du (Achtung: Sehr langsam!):

    valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes --track-origins=yes dein_programm
    

    Damit werden dir auch Hinweise über die Ursache des Fehler gegeben.

    Debugsymbole hattest du übrigens wohl auch nicht benutzt, zumindest nicht für den hier interessanten Teil.



  • Conditional jump or move depends on uninitialised value(s)

    Das bedeutet, dass da ein if oder sonst eine Bedingung von einer Variablen abhängt die nicht initialisiert ist. Was steht denn genau an der Stelle?



  • bool b; // Kann irgendeinen Wert haben da nicht initialisiert.
    if(b)
        mach_das();
    else
        mach_dies();
    

    Es ist vollkommen undefiniert und zufällig ob Ersteres oder Zweiteres ausgeführt wird.
    Das ist ein dicker Fehler.


Anmelden zum Antworten