Speicher wird nicht mehr freigegeben ?!?!



  • taff schrieb:

    nur sollten sich nicht 1024byte einer variable die einmal angelegt wurden nicht auf andere 50mb im speicher auswirken, oder?

    Ob sie es sollten, ist eine Design-Frage. Ich sage mal so: ich erwarte sowas nicht in meiner aktuellen Umgebung. Aber ich sage, das es passieren kann, wenn es der Allokator, CRT oder OS so wollen. Und das ist der entscheidende Punkt, wo du dich von mir unterscheidest. Du willst es nicht wahrhaben und nicht akzeptieren. Ich würde darüber nicht erfreut sein, könnte es akzeptieren, wenn mir der Designer des Allokator, CRT oder OS es mir erklärt, weil er es so wollte und toll findet.

    Wenn ich damit nicht leben kann, muß ich handeln! Und zwar den "Übeltäter" ausfindig machen, und ihn auswechseln!

    taff schrieb:

    ähm valgrind ist ein memoryleak tool .... ev hast du das überlesen! und wie gesagt hier liefert mir valgrind das alle angelegten objekte zerstört und freigegeben wurden und trotzdem bleiben im top bei meiner pid in der RES spalte 50mb über.

    Sorry, bin nicht Linux-bewandert. Muß bei mir untergegangen sein. 😉 Gut, aber dieses Memoryleakdetector-Tool namens valgrind sagt dir: "In deinem C++-Programm, das DU geschrieben hast, hast du alles formal korrekt gemacht, was Resourcenfreigabe betrifft."
    So, das sagt mir, das du somit dieses Topic in diesem Forum abschliessen kannst. Weil ISO-C++-mäßig gibt es keine Fragen mehr.

    taff schrieb:

    leider ist mir der speicherverbrauch nciht egal, weil wenn ein dienst zb. 500mb auf diese art und weise auf einer diskless maschine verbraucht und dann 5000 kunden dadurch mehr ram brauchen, dann ist das in meinen augen schon ein problem

    Yo, das glaube ich dir gerne. Nur mußt du herausfinden, warum das so ist. Aber du suchst an der falschen Stelle. Das sagt dir auch Valgrind, weshalb ich nach dessen Ergebnis gefragt habe.

    Ich würde jetzt mal folgendes machen: den Support für deine CRT und dein OS fragen, wie die Speicherallokierung und Freigabe funktioniert. (wobei ich erst bei der CRT anfangen würde!) Nur die können dir die Frage beantworten, was im Hintergrund passiert und warum das so extrem ist. Und ich wette, du wirst zu dem Ergebnis kommen, das du eine Komponente austauschen werden mußt. Im einfachsten Fall nur den Allokator. Evtl. kannst du ihn auch selber schreiben. Oder eine andere CRT oder Compiler benutzen, die eher für Diskless-HW designed und implementiert ist.

    Im schlimmsten Fall das OS auswechseln! (Und dann müsstest du deinen Kunden halt ein bestimmtes OS vorschreiben, was für Diskless-Rechner geeignet ist.)



  • Wenn du Angst hast, dein Programm könnte durch das "tausendemale übergeben" von großen Objekten zu viel Speicher fressen, dann übergib deine Riesen-Objekte doch nicht so oft - neben dem Speicherplatz kostet das nämlich auch Laufzeit. (zur Not kannst du auch (const)Referenzen übergeben ;))

    taff schrieb:

    das allokator "problem" sollte eigentlich mit dem "swap-trick" behoben sein.

    Nein, ist es vermutlich nicht - mit dem Swap-Trick gibst du nur den ungenutzten Speicherplatz des vectors an den Allocator zurück, was der damit macht, ist seine Angelegenheit (normalerweise sollte der diesen Speicher entweder ans System zurückgeben oder dem nächsten vector zuschanzen, der ihn benötigt).



  • Artchi schrieb:

    Ob sie es sollten, ist eine Design-Frage. Ich sage mal so: ich erwarte sowas nicht in meiner aktuellen Umgebung. Aber ich sage, das es passieren kann, wenn es der Allokator, CRT oder OS so wollen. Und das ist der entscheidende Punkt, wo du dich von mir unterscheidest. Du willst es nicht wahrhaben und nicht akzeptieren. Ich würde darüber nicht erfreut sein, könnte es akzeptieren, wenn mir der Designer des Allokator, CRT oder OS es mir erklärt, weil er es so wollte und toll findet.

    ich will es nicht wahrhaben, wenn im falle der speichernot dieser speicher nicht freigegeben wird, dass es nicht sofort freigegeben wird, darüber bin ich nicht glücklich.

    Artchi schrieb:

    Wenn ich damit nicht leben kann, muß ich handeln! Und zwar den "Übeltäter" ausfindig machen, und ihn auswechseln!

    wird mir leider nicht übrigbleiben, da ich auch schon mir ganz normale verkettete listen und strings gebastelt habe, damit ich keine abhängigkeiten von der stl habe - gleicher effekt.

    Artchi schrieb:

    Im schlimmsten Fall das OS auswechseln! (Und dann müsstest du deinen Kunden halt ein bestimmtes OS vorschreiben, was für Diskless-Rechner geeignet ist.)

    das wird wohl der schwierigste teil werden, wenn das ganze auf jedem 0815 suse und konsorten laufen soll

    DANKE jedenfalls für deine hilfe und dein verständnis! 👍

    CStoll schrieb:

    Wenn du Angst hast, dein Programm könnte durch das "tausendemale übergeben" von großen Objekten zu viel Speicher fressen, dann übergib deine Riesen-Objekte doch nicht so oft - neben dem Speicherplatz kostet das nämlich auch Laufzeit. (zur Not kannst du auch (const)Referenzen übergeben )

    nein die angst habe ich nicht, da ich ja nur den pointer übergebe auf dieses char-array und wenn mein vector-element im stack angelegt wird dann übergebe ich auch 50.000 mal 1024 bytes und ich habe am ende nicht das problem, jedoch wenn ich das vector-element im heap anlege, dann ist es auch entscheidend wo ich diese buffer-varialbe anlege. 🙄

    CStoll schrieb:

    Nein, ist es vermutlich nicht - mit dem Swap-Trick gibst du nur den ungenutzten Speicherplatz des vectors an den Allocator zurück, was der damit macht, ist seine Angelegenheit (normalerweise sollte der diesen Speicher entweder ans System zurückgeben oder dem nächsten vector zuschanzen, der ihn benötigt).

    wie gerade oben beschrieben bei einer selbstgebauten liste usw. genau das gleiche problem.



  • ups doppelt



  • also wenn ich das programm mal schnell überfliege, dann sehe ich
    dort das selber problem wie beim OS,
    mal legt 1000 sachen aufm heap an, und will die dann löschen,
    new und delete von c++ sind aber auch so optimiert das sie zB speicherfragmentierung entgegenwirken

    ich denke das delete sich den block von 50MB erstmal warmhält,
    dann hast du das selbe problem mit "cache" wie beim OS.

    Dir bleiben also 2 Möglichkeiten :

    1. du kommst wieder wenn das Problem zu einem ECHTEM problem geworden ist,
    (50MB sind nämlich kein problem),
    und ich glaube kaum das sich das Problem zu 200MB expandieren lässt,
    dann hätten sich nämlich schon andere Leute beschwert, und das problem gäbe es nichtmehr

    2. du überschreibst operator new

    new und delete sind nämlich nicht malloc und free



  • nein die angst habe ich nicht, da ich ja nur den pointer übergebe auf dieses char-array und wenn mein vector-element im stack angelegt wird dann übergebe ich auch 50.000 mal 1024 bytes und ich habe am ende nicht das problem, jedoch wenn ich das vector-element im heap anlege, dann ist es auch entscheidend wo ich diese buffer-varialbe anlege.

    Öhm, das verstehe ich jetzt nicht. Wo du den vector anlegst, ist nämlich egal. Auch wenn er im Stack liegt, muß er nicht kopiert werden. Bsp.:

    void foo1(std::vector<irgendwas> &vec);    // vector wird NICHT kopiert
    void foo2(std::vector<irgendwas> vec);    // vector wird kopiert
    

    foo1 ist es sowas von Schnuppe, ob vector mal auf dem Heap oder Stack abgelegt wurde.



  • Treb schrieb:

    ich denke das delete sich den block von 50MB erstmal warmhält,
    dann hast du das selbe problem mit "cache" wie beim OS.

    wie schon mal erwähnt, warum wird dann der speicher aber freigegeben, wenn ich auch die übergabevariable mit dem namen buffer nicht am stack anlege sondern im heap, dann dürfte dies nicht so viel ausmachen ....

    Treb schrieb:

    1. du kommst wieder wenn das Problem zu einem ECHTEM problem geworden ist,
    (50MB sind nämlich kein problem),
    und ich glaube kaum das sich das Problem zu 200MB expandieren lässt,
    dann hätten sich nämlich schon andere Leute beschwert, und das problem gäbe es nichtmehr

    bitte erhöhe einfach das #define LIST_COUNT von 5 auf 20 und du hast am ende 194MB im speicher liegen! und ob 50mb ein problem sind oder nicht, sollte hier nicht die frage sein, weil ev. habe ich einen diskless-server mit 256mb ram, dann sind 50mb auch sehr viel, oder?

    [quote=Artchi]Öhm, das verstehe ich jetzt nicht. Wo du den vector anlegst, ist nämlich egal. Auch wenn er im Stack liegt, muß er nicht kopiert werden. Bsp.: [/quote]nein ich glaube wir reden gerade von 2 sachen. wenn das element eines vectors im stack oder heap liegt -> vector<irgendwas*>

    aber ich poste hier nun einfach mal 3 versionen meiner testprogramme:

    1. alles liegt im stack und und dank des swap-trickes habe ich am ende alles freigegeben
    #define LIST_COUNT 5
    #define BUFFER_SIZE 1024
    #define BUFFER_ADDS 10000
    
    class Data 
    {
    	public:
    		string name;
    
    	public:
    		Data() {}
    		~Data() {}
    		void Set(const char* _name) {name = _name;}
    };
    
    class DataList
    {
    	private:
    		 vector<Data> dataList;	
    
    	public:
    		DataList() {};
    		~DataList() { Clear();}
    
    		void Clear()
    		{
    			cout << "DataList::Clear()" << endl;
    			dataList.clear();
    			vector<Data>().swap(dataList);
    
    		}
    
    		void Add(const char *_name)
    		{
    			Data dataobj;
    
    			// Name setzen ----
    			if (_name) dataobj.Set(_name);
    
    			// Element in Liste hinzfügen
    			dataList.push_back (dataobj);
    		}
    };
    
    int main ()
    {
    	char buffer[BUFFER_SIZE+1];
    
    	memset(buffer, 'A', BUFFER_SIZE);
    	buffer[BUFFER_SIZE] = '\0';
    
    	DataList datalist[LIST_COUNT];
    
    	for(int idx=0; idx<LIST_COUNT; idx++)
    	{
    		for(int i=0; i<BUFFER_ADDS; i++)
    			datalist[idx].Add(buffer);
    	}
    
    	for(int idx=0; idx<LIST_COUNT; idx++)
    		datalist[idx].Clear();
    
    	while(1)
    		sleep(1);
    
    }
    
    1. ich verwende als vector-daten-element einen pointer auf meine Data-Klasse und die klasse die als member einen vector besitzt wird auch im heap angelegt, alle wichtigen änderungen sind fettgedruckt - am ende bleiben mir ~50mb über
    #define LIST_COUNT 5
    #define BUFFER_SIZE 1024
    #define BUFFER_ADDS 10000
    
    class Data 
    {
    	public:
    		string name;
    
    	public:
    		Data() {}
    		~Data() {}
    		void Set(const char* _name) {name = _name;}
    };
    class DataListPointer
    {
    	private:
    		 [b]vector<Data*> dataList;[/b]	
    
    	public:
    		DataListPointer() {}
    		virtual ~DataListPointer() { }
    
    		void Clear()
    		{
    			cout << "DataListPointer::Clear()" << endl;
    			for(uint i=0; i< dataList.size(); i++)
    			{
    				[b]delete dataList.at(i);[/b]
    				[b]dataList.at(i) = NULL;[/b]
    			}
    			dataList.clear();
    			vector<Data*>().swap(dataList); 		}
    
    		void Add(const char *_name)
    		{
    			[b]Data *dataobj(new Data());[/b]
    
    			// Name setzen ----
    			if (_name) dataobj->Set(_name);
    
    			// Element in Liste hinzfügen
    			dataList.push_back (dataobj);
    		}
    };
    
    int main ()
    {
    	char buffer[BUFFER_SIZE+1];
    	memset(buffer, 'A', BUFFER_SIZE);
    	buffer[BUFFER_SIZE] = '\0';
    
    	[b]DataListPointer *datalist[LIST_COUNT];[/b]
    
    	for(int idx=0; idx<LIST_COUNT; idx++)
    	{
    		[b]datalist[idx] = new DataListPointer();[/b]
    		for(int i=0; i<BUFFER_ADDS; i++)
    			datalist[idx]->Add(buffer.c_str());
    	}
    
    	for(int idx=0; idx<LIST_COUNT; idx++)
    	{
    		datalist[idx]->Clear();
    		[b]delete datalist[idx];[/b]
    		[b]datalist[idx] = NULL;[/b]
    	}
    
    	while(1)
    		sleep(1);
    
    }
    
    1. ist fast so ähnlich wie das 2 beispiel, jedoch mit einer kleinen änderung, dass die buffer-variable im heap liegt. erst wenn ich das delete auf die buffer-variable mache, werden mir auch die schon von mir freigegeben ~50mb "richtig" freigegeben. fett gedruckt sind die änderungen zu beispiel 2
    int main ()
    {
    	[b]char *buffer = new char[BUFFER_SIZE+1];[/b]
    	memset(buffer, 'A', BUFFER_SIZE);
    	buffer[BUFFER_SIZE] = '\0';
    
    	DataListPointer *datalist[LIST_COUNT];
    
    	for(int idx=0; idx<LIST_COUNT; idx++)
    	{
    		datalist[idx] = new DataListPointer();
    		for(int i=0; i<BUFFER_ADDS; i++)
    			datalist[idx]->Add(buffer);
    	}
    
    	for(int idx=0; idx<LIST_COUNT; idx++)
    	{
    		datalist[idx]->Clear();
    		delete datalist[idx];
    		datalist[idx] = NULL;
    	}
    
    	[b]delete buffer;[/b]
    
    	while(1)
    		sleep(1);
    
    }
    


  • Hallo,

    ich habe dein Testprogramm von Seite 1 mal bei mir laufen lassen. Bei mir wird
    kein Speicher festgehalten, er steigt bei mir nicht mal auf 50MB. Ich habe
    konstant knapp 8MB RES, das wars auch schon.

    Bei deiner ersten geposteten Aenderung, sinkt die RES auf ca. 3,7MB. Wieder
    werden keine 50MB bis Programmende gehalten.

    Dann habe ich deine naechst geposteten main-Funktionen ausprobiert und auch
    Braunsteins Code eingebaut. In allen Faellen hat sich an meinem Speicher-
    verbrauch nichts geaendert.

    In allen deinen 3 Programmen, kann ich das Problem auf meinem System
    nicht nachvollziehen.

    Aber wie die anderen bereits gesagt haben:
    Speicher ist etwas, was das OS dem Programm zuordnet. Wenn du Speicher wieder
    freigibst, heisst das nicht, dass das OS diese Zuordnung direkt wieder
    aufhebt. Um evtl. weiteren Speicheranforderungen schnell Rechnung zu tragen,
    wird es, vor allem wenn es erkennt, dass du sehr haeufig Speicher anforderst,
    diese Zuordnung nicht aufheben. Dir bleibt dann der Speicher zugeordnet und
    daran kannst du auch erstmal nichts dran aendern.

    Ob es sich bei dieser Zuordnung nun um mehr oder weniger als 50MB handelt,
    ist eine Entscheidung, welche das OS faellt und von dir nicht beeinflussbar
    ist.

    Das System mit welchem ich testen kann:

    FreeBSD 7.0-BETA4.

    gruss
    v R



  • virtuell Realisticer schrieb:

    ich habe dein Testprogramm von Seite 1 mal bei mir laufen lassen. Bei mir wird ein Speicher festgehalten, er steigt bei mir nicht mal auf 50MB. Ich habe konstant knapp 8MB RES, das wars auch schon.

    Bei deiner ersten geposteten Aenderung, sinkt die RES auf ca. 3,7MB. Wieder werden keine 50MB bis Programmende gehalten.

    DANKE das du gestestet hast! 🙂 also das beispiel auf der ersten seite ist eigentlich dank dem swap-trick für mich gelöst. aber anders sieht es zb. aus mit dem 2. und 3. beispiel in meinem letzten posting. hast du dort auch überall deine freigaben (bin mir nicht sicher ob du in deinem beitrag diese beispiele dann meinst) ?

    virtuell Realisticer schrieb:

    Aber wie die anderen bereits gesagt haben:
    Speicher ist etwas, was das OS dem Programm zuordnet. Wenn du Speicher wieder freigibst, heisst das nicht, dass das OS diese Zuordnung direkt wieder aufhebt. Um evtl. weiteren Speicheranforderungen schnell Rechnung zu tragen, wird es, vor allem wenn es erkennt, dass du sehr haeufig Speicher anforderst, diese Zuordnung nicht aufheben. Dir bleibt dann der Speicher zugeordnet und daran kannst du auch erstmal nichts dran aendern.

    solange dieser nur mir zugeordnet bleibt, wenn keine speichernot herscht, kann ich mich damit abfinden, jedoch sieht das anders aus, wenn ich einen zweiten dienst starte und der legt mir eben statt 10.000 vector elementen 1.000.000 an, dann geht der maschine der speicher aus und bevor der speicher ausgeht, sollte doch der freie speicher von meinem testprogramm verwendet/abgezogen werden oder? leider hat mein test damals das nicht gemacht.

    virtuell Realisticer schrieb:

    Ob es sich bei dieser Zuordnung nun um mehr oder weniger als 50MB handelt, ist eine Entscheidung, welche das OS faellt und von dir nicht beeinflussbar ist.

    die 50MB sind nur ein beispiel, weil verändere ich die define-werte, dann verändert sich auch das verhalten wieviel speicher am ende noch übrig bleibt.

    virtuell Realisticer schrieb:

    FreeBSD 7.0-BETA4.

    ich habe auf einem fedora core 2, fedora core 5, ubuntu 7.1, suse 8.1 getestet, es wurden nirgends updates gemacht und hatte überall die gleichen "probleme"



  • Hallo,

    taff schrieb:

    virtuell Realisticer schrieb:

    ich habe dein Testprogramm von Seite 1 mal bei mir laufen lassen. Bei mir wird ein Speicher festgehalten, er steigt bei mir nicht mal auf 50MB. Ich habe konstant knapp 8MB RES, das wars auch schon.

    Bei deiner ersten geposteten Aenderung, sinkt die RES auf ca. 3,7MB. Wieder werden keine 50MB bis Programmende gehalten.

    DANKE das du gestestet hast! 🙂 also das beispiel auf der ersten seite ist eigentlich dank dem swap-trick für mich gelöst. aber anders sieht es zb. aus mit dem 2. und 3. beispiel in meinem letzten posting. hast du dort auch überall deine freigaben (bin mir nicht sicher ob du in deinem beitrag diese beispiele dann meinst) ?

    Die von dir zuletzt geposteten bringen folgendes Resultat:

    Programm 1: Zugesicherter Speicher: 3660K
    Programm 2: Zugesicherter Speicher: 3704K
    Programm 3: Zugesicherter Speicher: 3700K

    virtuell Realisticer schrieb:

    Aber wie die anderen bereits gesagt haben:
    Speicher ist etwas, was das OS dem Programm zuordnet. Wenn du Speicher wieder freigibst, heisst das nicht, dass das OS diese Zuordnung direkt wieder aufhebt. Um evtl. weiteren Speicheranforderungen schnell Rechnung zu tragen, wird es, vor allem wenn es erkennt, dass du sehr haeufig Speicher anforderst, diese Zuordnung nicht aufheben. Dir bleibt dann der Speicher zugeordnet und daran kannst du auch erstmal nichts dran aendern.

    solange dieser nur mir zugeordnet bleibt, wenn keine speichernot herscht, kann ich mich damit abfinden, jedoch sieht das anders aus, wenn ich einen zweiten dienst starte und der legt mir eben statt 10.000 vector elementen 1.000.000 an, dann geht der maschine der speicher aus und bevor der speicher ausgeht, sollte doch der freie speicher von meinem testprogramm verwendet/abgezogen werden oder? leider hat mein test damals das nicht gemacht.

    Ja das ist merkwuerdig. Das ist bei mir gar nicht der Fall.

    virtuell Realisticer schrieb:

    Ob es sich bei dieser Zuordnung nun um mehr oder weniger als 50MB handelt, ist eine Entscheidung, welche das OS faellt und von dir nicht beeinflussbar ist.

    die 50MB sind nur ein beispiel, weil verändere ich die define-werte, dann verändert sich auch das verhalten wieviel speicher am ende noch übrig bleibt.

    Ja da hast du allerdings auch recht.

    virtuell Realisticer schrieb:

    FreeBSD 7.0-BETA4.

    ich habe auf einem fedora core 2, fedora core 5, ubuntu 7.1, suse 8.1 getestet, es wurden nirgends updates gemacht und hatte überall die gleichen "probleme"

    Welche Kernelversion nutzt du?

    gruss
    v R



  • virtuell Realisticer schrieb:

    Die von dir zuletzt geposteten bringen folgendes Resultat:

    Programm 1: Zugesicherter Speicher: 3660K
    Programm 2: Zugesicherter Speicher: 3704K
    Programm 3: Zugesicherter Speicher: 3700K

    bei beispiel 1 und beispiel 2 geht am ende mein speicherverbrauch auf 1052K zurück

    virtuell Realisticer schrieb:

    Welche Kernelversion nutzt du?

    beim suse habe ich 2.4.19 und dort habe ich mir mittels kdevelop ein auto-make file erstellen lassen, damit auch mal vom firmen internen standard-makefile löse usw. ansonsten reichen die anderen version von 2.6.5 bis 2.6.20



  • taff schrieb:

    virtuell Realisticer schrieb:

    Die von dir zuletzt geposteten bringen folgendes Resultat:

    Programm 1: Zugesicherter Speicher: 3660K
    Programm 2: Zugesicherter Speicher: 3704K
    Programm 3: Zugesicherter Speicher: 3700K

    bei beispiel 1 und beispiel 2 geht am ende mein speicherverbrauch auf 1052K zurück

    Naja wie gesagt, der zugesicherte Speicher hat wenig aussagekraft.

    virtuell Realisticer schrieb:

    Welche Kernelversion nutzt du?

    beim suse habe ich 2.4.19 und dort habe ich mir mittels kdevelop ein auto-make file erstellen lassen, damit auch mal vom firmen internen standard-makefile löse usw. ansonsten reichen die anderen version von 2.6.5 bis 2.6.20

    Ein Linux hab ich leider nicht hier, wenn ich mal wieder zu meinem Nebenjob
    gehe, werd ich dort mal die Testprogramme auf einigen Linuxkisten laufen
    lassen.

    gruss
    v R



  • virtuell Realisticer schrieb:

    Naja wie gesagt, der zugesicherte Speicher hat wenig aussagekraft

    das sowieso, aber danke für deine bemühungen.

    gestern abend habe ich noch einwenig weitergetestet und mir mal folgendes angesehen: was passiert, wenn ich nach dem löschen meines vectors wieder weitere datenelemente anlege und lösche und war dann doch wieder mal überrascht und auf mich selbst verärgert.

    ich habe ganz am ende (also vor der while-schleife mit dem sleep) folgendes eingefügt:

    while(0)
    	{
    		sleep(3);
    
    		Data* arr[BUFFER_ADDS];
    		for(int i=0; i<1; i++)
    		{
    			arr[i] = new Data();
    			arr[i]->Set(buffer);
    		}
    		for(int i=0; i<1; i++) // lösche ich meinen buffer hier nicht, dann wird auch der andere schon reservierte buffer nicht "total" freigegeben
    			delete arr[i];
    	}
    

    das ergebnis ist:

    1. der speicher reduziert sich auf 11MB
    2. mache ich von diesem neu angelgten buffer kein delete, wird der speicher deshalb auch nicht weniger.
    3. der nun neu angelegte speicher behält den "status" reserviert obwohl alles freigegeben wurde -> somit weitere 11MB die eigentlich frei wären und trotzdem mir zugeordnet werden.

    getrieben mit diesen erkenntnissen habe ich nun folgende tests durchgeführt und den obigen code durch diesen hier ersetzt:

    if(1)
    {
    	double d1(0.0);
    	double d2(0.0);
    	int i(1);
    	char buf1[10];
    	memset(buf1, 'A', 10);
    	buf1[10]= '/0';
    
    	string str;
    	str.append(10,'a');
    	str.clear();
    }
    

    es gibt hier keinen erfolg. ich habe das ganze in einen block geschrieben, damit meine variablen im stack auch wieder zerstört werden.

    if(1)
    {
    	double d1(0.0);
    	double d2(0.0);
    	int i(1);
    	char buf1[10];
    	memset(buf1, 'A', 1000);
    	buf1[10]= '/0';
    
    	string str;
    	str.append(1000,'a');
    	str.clear();
    }
    

    erfolg ist da! speicher wird wieder zu meiner zufriedenheit freigegeben. und habe am ende 1056KB zugewiesenen speicher. wobei ich wieder ausfindig machen konnte, dass der hier angelegte speicher mir wieder nach dem blockende wieder "reserviert" bleibt. was ich hier noch hinterfragen möchte, warum muss eine gewisse speichergröße überschritten werden, damit der mir zuvor zugeordnete freie speicher freigegeben wird?

    eigentlich könnte man nun sagen, mein problem ist gelöst - EIGENTLICH.
    wenn man nun so wie ich es aber benötige, am anfang viele daten einlese, später zb. in diesem array jeden zweiten vector zerstöre und mit den dadurch entstandenen daten arbeite und dann außer find-methoden aufrufen nicht mehr viel mache, sprich keine weiteren großen speicherblöche mehr anlege, schleppe ich freien zugeordneten speicher mit, welchen leider keine andere application mehr abzweigen kann, wenn speichernot herscht.



  • Nabend,

    taff schrieb:

    virtuell Realisticer schrieb:

    Naja wie gesagt, der zugesicherte Speicher hat wenig aussagekraft

    das sowieso, aber danke für deine bemühungen.

    gestern abend habe ich noch einwenig weitergetestet und mir mal folgendes angesehen: was passiert, wenn ich nach dem löschen meines vectors wieder weitere datenelemente anlege und lösche und war dann doch wieder mal überrascht und auf mich selbst verärgert.

    ich habe ganz am ende (also vor der while-schleife mit dem sleep) folgendes eingefügt:

    while(0)
    	{
    		sleep(3);
    
    		Data* arr[BUFFER_ADDS];
    		for(int i=0; i<1; i++)
    		{
    			arr[i] = new Data();
    			arr[i]->Set(buffer);
    		}
    		for(int i=0; i<1; i++) // lösche ich meinen buffer hier nicht, dann wird auch der andere schon reservierte buffer nicht "total" freigegeben
    			delete arr[i];
    	}
    

    das ergebnis ist:

    1. der speicher reduziert sich auf 11MB
    2. mache ich von diesem neu angelgten buffer kein delete, wird der speicher deshalb auch nicht weniger.

    Naja, das ist ja klar. Von dir reservierter Speicher muss auch wieder
    freigegeben werden. Alternativ dazu kannst du boost::ptr_vector verwenden.

    1. der nun neu angelegte speicher behält den "status" reserviert obwohl alles freigegeben wurde -> somit weitere 11MB die eigentlich frei wären und trotzdem mir zugeordnet werden.

    Nur damit ich dich nicht falsch verstehe:

    Zunaechst hast du den alten Speicherplatz freigegeben und dann den neuen
    Puffer reserviert. Dann hast du diesen wieder freigegeben und der Speicher-
    platz bleibt deiner Anwendung zugeordnet.

    Dieses Verhalten ist zunaechst einmal nicht weiter schlimm.

    Hast du nach wie vor das Problem, dass auch bei Speicherknappheit dieser
    Speicherplatz fuer dein Programm erhalten bleibt?

    getrieben mit diesen erkenntnissen habe ich nun folgende tests durchgeführt und den obigen code durch diesen hier ersetzt:

    if(1)
    {
    	double d1(0.0);
    	double d2(0.0);
    	int i(1);
    	char buf1[10];
    	memset(buf1, 'A', 10);
    	buf1[10]= '/0';
    
    	string str;
    	str.append(10,'a');
    	str.clear();
    }
    

    es gibt hier keinen erfolg. ich habe das ganze in einen block geschrieben, damit meine variablen im stack auch wieder zerstört werden.

    Was dafuer sprechen koennte, dass der Stack noch nicht verkleinert worden
    ist. Ein Hinweis von Freundlich (aus dem irc):

    Freundlich schrieb:

    17:22 <Freundlich> Es kann sehr gut sein, dass da nirgendwo was gel"oscht wird.
    17:23 <Freundlich> string nutzt normalerweise COW oder small-buffer-optimization.
    17:23 <Freundlich> clear l"oscht nichts.
    17:23 <Freundlich> Also wird da nichts freigegeben.

    if(1)
    {
    	double d1(0.0);
    	double d2(0.0);
    	int i(1);
    	char buf1[10];
    	memset(buf1, 'A', 1000);
    	buf1[10]= '/0';
    
    	string str;
    	str.append(1000,'a');
    	str.clear();
    }
    

    erfolg ist da! speicher wird wieder zu meiner zufriedenheit freigegeben. und habe am ende 1056KB zugewiesenen speicher. wobei ich wieder ausfindig machen konnte, dass der hier angelegte speicher mir wieder nach dem blockende wieder "reserviert" bleibt. was ich hier noch hinterfragen möchte, warum muss eine gewisse speichergröße überschritten werden, damit der mir zuvor zugeordnete freie speicher freigegeben wird?

    buf1 hat nur 10 Elemente!

    eigentlich könnte man nun sagen, mein problem ist gelöst - EIGENTLICH.
    wenn man nun so wie ich es aber benötige, am anfang viele daten einlese, später zb. in diesem array jeden zweiten vector zerstöre und mit den dadurch entstandenen daten arbeite und dann außer find-methoden aufrufen nicht mehr viel mache, sprich keine weiteren großen speicherblöche mehr anlege, schleppe ich freien zugeordneten speicher mit, welchen leider keine andere application mehr abzweigen kann, wenn speichernot herscht.

    Wie gesagt, dieses Verhalten ist mir schleierhaft und ich kann es auf meinem
    System nicht nachvollziehen. Wenn es dir nicht zuviel Aufwand ist, koenntest
    du mal auf eines der Systeme einen aktuellen Kernel kompilieren und den
    Test wiederholen.

    Noch ein kleiner Hinweis von Freundlich, der sich das auch mal angeschaut
    hat:

    Bei deinem dritten geposteten Programm musst du am schluss delete[] aufrufen
    und nicht delete, du hast schliesslich ein Array allokiert.

    gruss
    v R



  • guten morgen!

    virtuell Realisticer schrieb:

    Naja, das ist ja klar. Von dir reservierter Speicher muss auch wieder
    freigegeben werden. Alternativ dazu kannst du boost::ptr_vector verwenden.

    meine überlegung war folgende, wenn ich nun vor dem while wo der vector+array schon freigegeben wurde, einfach was anlege und ich das neu angelegte nicht freigebe, ob ich hier auch schon veränderungen meines freigegeben und trotzdem noch zugewiesenen speicher von vorhin habe. wie gesagt die neuen variablen müssen auch freigegeben werden, dann kann sich erst was auswirken.

    virtuell Realisticer schrieb:

    Nur damit ich dich nicht falsch verstehe:

    Zunaechst hast du den alten Speicherplatz freigegeben und dann den neuen
    Puffer reserviert. Dann hast du diesen wieder freigegeben und der Speicher-
    platz bleibt deiner Anwendung zugeordnet.

    Dieses Verhalten ist zunaechst einmal nicht weiter schlimm.

    Hast du nach wie vor das Problem, dass auch bei Speicherknappheit dieser
    Speicherplatz fuer dein Programm erhalten bleibt?

    genau so ist es!
    zuerst habe ich ~50mb freigegebenen mir zugeordneten speicher und dann sind es 11mb freigegebener zugeordneter speicher, wobei hier auch gilt, lege ich mehr speicher an, dann könnten es auch am ende 100mb sein. starte ich mein testprogramm, welches einfach nur speicher belegt wird, kann dieses auch nicht auf den freiggegeben zugeordneten speicher zugreifen.

    virtuell Realisticer schrieb:

    buf1 hat nur 10 Elemente!

    sorry mein fehler hier beim posting, habe die 1000-elemente version hier zuerst reinkopiert und dann vergessen dies beim memset richtig zu stellen, also getestet wurde natürlich mit der 10elemente version.

    virtuell Realisticer schrieb:

    Noch ein kleiner Hinweis von Freundlich, der sich das auch mal angeschaut
    hat:

    Bei deinem dritten geposteten Programm musst du am schluss delete[] aufrufen
    und nicht delete, du hast schliesslich ein Array allokiert.

    ups stimmt, danke! die buffer-variable muss ich natürlich so freigegeben, wobei wie gerade getestet dies keine weiteren auswirkungen hat und der schon freigegebene und mir zurgeordnete speicher trotzdem nachdem

    delete[] buffer;
    

    nun total freigegeben wird. (war vorher mittels delete ohne [] auch so)

    werde mir am wochenende eine linux umgebung auf den neuesten stand der dinge bringen, also kernel stable version 2.6.23.9



  • Hallo,

    ja das waere sehr interessant, wenn du das machst und mal postest, ob sich
    dann etwas an dem Verhalten aendert.

    Fuer mich ist es leider schwer da nach Loesungen zu suchen, da bei mir dieses
    Problem gar nicht auftritt, ich kann also nur Vermutungen anstellen :).

    gruss
    v R



  • so, mit verspätung aber doch noch, kann ich nun "infos" zu den tests mit dem 2.6.23.9 kernel posten.
    getestet wurde mittels vmware, fedora core 8, kdevelop und eben dem aktuellen stable kernel

    kurz und bündig es ändert sich nichts! 😞

    ich habe die 3 beispiele von der vorseite ausprobiert, sowie mit der zusätzlichen speicher reservierung und freigabe vor der while-sleep schleife wie auf dieser seite schon besprochen - das verhalten bleibt gleich!
    zusätzlich habe ich wieder bei einer version wo mir 42mb übrig geblieben sind einen anderen service gestartet der mir einfach speicher frisst, leider wurden auch hier wieder die 42mb bei speichernot nicht freigegeben!

    😞



  • Vor langer langer Zeit hatte ich Probleme mit der Speicherfreigabe und da ich vor kurzem auf eine mögliche Lösung gestoßen bin, möchte ich die hier der vollständigkeithalber die auch veröffentlichen:

    Mit diesem Befehl wird wieder alles "richtig" freigegeben.

    malloc_trim(0);
    

    Angeblich kann man mittels

    int mallopt(int param, int value);
    

    das ganze nach seinen bedürfnissen einstellen.
    Falls es jemanden gibt der mehr darüber weiß, der darf ruhig dies auch kund tun 🙂


  • Mod

    Ich habe deinen letzten Beitrag nicht umsonst gelöscht. Niemand wird sich 6 Seiten eines 6 Jahre alten Threads durchlesen und niemand weiß mehr, worum es geht!

    Wenn du Fragen hast, dann mach einen neuen Thread auf, in dem du dein Problem vollständig erklärst, so dass man auch ohne Hintergrundwissen über antike Forengeschichte deine Frage verstehen kann. Sei dir auch sicher, dass du im richtigen Forum fragst, malloc_trim und mallopt sind Linuxfunktionen.


Anmelden zum Antworten