2009-08-14 6 views
3

hier ist ein einfacher d/Tango-Code in den Fenstern:malloc und frei in D/Tango Speicher nicht freigeben?

module d_test.d; 

import tango.util.log.Trace; 
import tango.core.Thread; 
import tango.stdc.stdlib : malloc, free; 

void main() { 

    Trace.formatln("Checking in..."); 
    Thread.sleep(10); 

    int total_n = (100 * 1000 * 1000)/int.sizeof; // fill mem with 100MB of ints 
    int* armageddon = cast(int*)malloc(total_n * int.sizeof); 

    for(int i = 0; i < total_n; ++i) { 
     armageddon[i] = 5; 
    } 

    Trace.formatln("Checking in..."); 
    Thread.sleep(10); 

    free(armageddon); 
    armageddon = null; 

    Trace.formatln("Checking in..."); 
    Thread.sleep(10); 


} 

, wenn ich das Programm ausführen, Speicher niedrig bleibt ~ 2MB, und wenn ich ein Array von 100 MB auf die Zeiger Speichernutzung zuteiles springt auf ~ 100 MB, was in Ordnung ist. Nach dem freien Speicher ist jedoch immer noch (ich schaue auf Task-Manager) bei 100 MB bis zum Ende des Programms.

Ich dachte, es zu Windows Auslagerungsdatei Cache oder etwas sein könnte, also habe ich ein einfaches C++ Programm versucht:

#include <iostream> 
#include <windows.h> 

using namespace std; 

int main() { 

    Cout << "Checking in..." <<< endl; 
    Sleep(10000); 


    int total_n = (100 * 1000 * 1000)/sizeof(int); 
    int* armageddon = (int*)malloc(total_n * sizeof(int)); 

    for(int i = 0; i < total_n; ++i) { 
    armageddon[i] = 5; 
    } 

    Cout << "Checking in..." <<< endl; 
    Sleep(10000); 

    free(armageddon); 
    armageddon = NULL; 

    Cout << "Checking in..." <<< endl; 
    Sleep(10000); 


return 0; 
} 

Ich habe es mit g ++ kompiliert und alles scheint, wie es sollte zu funktionieren. Wenn das Programm startet - Speicherverbrauch ~ 900kb, nach Zuteilung ~ 100MB, nach freiem ~ 1,2MB ...

Also, was mache ich falsch oder ist das ein Fehler?

+1

malloc und kostenlos sind nur Rapper für die C-Anrufe. Ich weiß nicht, warum die Ergebnisse anders sein würden. –

+6

Yo yo! // mein Name ist malloc und ich bin ein böser Rapper. // Gib mir alle deine Erinnerungen, und ich werde es in den Crapper werfen – Baxissimo

Antwort

3

Es hängt davon ab, wie frei implementiert ist. Interessante Informationen finden Sie unter Doug Lea's allocator, die Speicheranforderungen, die eine Vielzahl von Größen abdecken können, effizient verwalten kann. Sein Hauptanliegen ist, dass die malloc und kostenlos Anrufe schnell und korrekt.

Aber er nicht erwähnt das Problem Speicher an das Betriebssystem zurückzukehren, und diskutiert, was es (Speicherfragmentierung) behindert und was hilft ihm (Verwendung von Mmap oder in einem weniger flexibel, sbrk) . Sobald Sie diesen Artikel gelesen haben, haben Sie eine klarere Vorstellung von den Kompromissen, die zu einer seltenen Rückkehr des Speichers zum Betriebssystem führen.

2

Wenn Sie Speicher mit "free" freigeben, ist es wahrscheinlich, dass es den Speicher tatsächlich nicht freigibt.

Es könnte sein, dass es es einfach als frei markiert, aber festhalten, wenn Sie später mehr Speicher anfordern. Wenn das System aus irgendeinem Grund nicht mehr genügend Speicher zur Verfügung hat, wird es möglicherweise zu diesem Zeitpunkt von der Laufzeitumgebung freigegeben.

+0

OK, wenn das stimmt - kennst du einen Weg, es mit Gewalt zu befreien? – Keyframe

+0

Warum brauchen Sie es, um zum Betriebssystem zurückzukehren? Solange Sie überhaupt über Swap-Speicher verfügen, hat der unbenutzte Datenspeicher ungefähr null Kosten. – BCS

+0

@BCS Ich überwache die Programmspeicherauslastung für die Profilerstellung, da ich bei Bedarf den Gesamtspeicherbedarf begrenzen möchte. Und ich bin auch neugierig, warum das so funktioniert, wie es funktioniert und wie ich es so machen kann, wie ich es möchte. – Keyframe

0

Sie können mit _heapmin() beginnen. free() gibt keinen unbenutzten Heap an das OS zurück, es markiert es nur als frei und fügt sich mit nächsten freien Nachbarn zusammen.

1

Das ist seltsam. Von der Tango-Quelle aus betrachtet, sind malloc/free in tango.stdc.stdlib nur die C-Standardbibliotheksfunktionen, also sollte es zu Recht keinen Unterschied geben - und tatsächlich, wenn ich es unter Linux mit Phobos und std.c.stdlib versuche , die Erinnerung geht wieder richtig runter wie es sollte.

Sind Sie sicher, dass Sie es richtig messen?

PS: Sie können einfach nicht armageddon [0 .. total_n] = 5;

PS2: Ich habe versucht, Ihre Tango-Code unter Linux, und es geht wieder nach unten, wie erwartet. Sieht nach einem Windows-Problem aus.

2

Es bedeutet nur, dass die Implementierung von malloc und free von Digital Mars keinen Speicher an das Betriebssystem zurückgibt, selbst wenn Sie einen riesigen Block wie diesen zuweisen. Sie könnten stattdessen versuchen, malloc und free von msvcrt.dll zu verwenden, vielleicht werden sie den Speicher freigeben.

Oder Sie können die Windows-API direkt verwenden, wenn dieses Problem nur für DMD unter Windows besteht.Am einfachsten ist es, die Funktionen HeapAlloc und HeapFree zu verwenden, aber ich weiß nicht, ob sie auch tun werden, was Sie wollen. Ein sicherer Weg ist das tiefer liegende VirtualAlloc und VirtualFree, die direkt vom Betriebssystem zugewiesen werden, anstatt zuerst einen Heap zu erstellen. Dies sind auch die Funktionen, die HeapAlloc, malloc, neu in C++, usw. verwenden, wenn sie Speicher vom Betriebssystem anfordern.

+1

um zu überprüfen, dass Sie das C++ - Programm mit DMC (dem digitalen Mars C++ Compiler) als IIRC versuchen können, es verwendet das gleiche malloc wie D. – BCS