Frage

Bitte helfen Sie :) Betriebssystem:Linux

Wo in „sleep(1000);“ schrieb mir zu diesem Zeitpunkt „top (Linux-Aufgaben anzeigen)“ 7,7 % MEM-Nutzung.Valgrind:Speicherleck nicht gefunden.

Ich verstehe, habe richtig geschrieben und alle Malloc-Ergebnisse sind NULL.Aber warum hat mein Programm in dieser Zeit „schlafen“ NICHT den Speicher verringert?Was fehlt?

Entschuldigung für mein schlechtes Englisch, Danke


~ # tmp_soft
For : Is it free??  no
Is it free??  yes
For 0 
For : Is it free??  no
Is it free??  yes
For 1 
END : Is it free??  yes
END 

~ #top
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                
23060 root      20   0  155m 153m  448 S    0  7.7   0:01.07 tmp_soft    

Vollständige Quelle:tmp_soft.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

struct cache_db_s
{
 int       table_update;
 struct    cache_db_s * p_next;
};

void free_cache_db (struct cache_db_s ** cache_db)
{
 struct cache_db_s * cache_db_t;
 while (*cache_db != NULL)
 {
  cache_db_t = *cache_db;
  *cache_db = (*cache_db)->p_next;
  free(cache_db_t);
  cache_db_t = NULL;
 }
 printf("Is it free??  %s\n",*cache_db==NULL?"yes":"no");
}

void make_cache_db (struct cache_db_s ** cache_db)
{
 struct cache_db_s * cache_db_t = NULL;
 int n = 10000000;

 for (int i=0; i = n; i++)
 {
  if ((cache_db_t=malloc(sizeof(struct cache_db_s)))==NULL) {
   printf("Error : malloc 1 -> cache_db_s (no free memory) \n");
   break;
  }
  memset(cache_db_t, 0, sizeof(struct cache_db_s));

  cache_db_t->table_update = 1; // tmp 

  cache_db_t->p_next = *cache_db;
  *cache_db = cache_db_t;
  cache_db_t = NULL;
 }
}

int main(int argc, char **argv)
{
 struct cache_db_s * cache_db = NULL;

 for (int ii=0; ii  2; ii++) {
  make_cache_db(&cache_db);
  printf("For : Is it free??  %s\n",cache_db==NULL?"yes":"no");
  free_cache_db(&cache_db);
  printf("For %d \n", ii);
 }

 printf("END : Is it free??  %s\n",cache_db==NULL?"yes":"no");
 printf("END \n");
 sleep(1000);
 return 0;
}
War es hilfreich?

Lösung

Wenn Sie feststellen möchten, ob Ihr Programm einen Speicherverlust aufweist, dann top ist nicht das richtige Werkzeug für den Job (valrind Ist).

top Zeigt die vom Betriebssystem erkannte Speichernutzung an.Auch wenn Sie anrufen free, gibt es keine Garantie dafür, dass der freigegebene Speicher an das Betriebssystem zurückgegeben wird.Normalerweise wäre das nicht der Fall.Dennoch wird der Speicher in dem Sinne „frei“, dass Ihr Prozess ihn für nachfolgende Zuweisungen verwenden kann.

bearbeiten Wenn dein libc unterstützt es, Sie könnten versuchen, damit zu experimentieren M_TRIM_THRESHOLD.Selbst wenn Sie diesem Weg folgen, wird es schwierig (ein einzelner verwendeter Block, der sich oben auf dem Heap befindet, würde verhindern, dass der gesamte freie Speicher darunter für das Betriebssystem freigegeben wird).

Andere Tipps

Aus guten Gründen kehrt praktisch kein Speicherplatz aus, um Blöcke auf das Betriebssystem zurückzugeben

Speicher kann nur aus Ihrem Programm in Seiten der Seiten entfernt werden, und sogar, dass es unwahrscheinlich ist, dass es nicht beachtet wird.

calcoc (3) und malloc (3) interagieren Sie ggf. mit dem Kernel, um den Speicher zu erhalten. Aber sehr, sehr wenige Implementierungen von freien (3) immer den Speicher in den Kernel 1 , sie fügen sie einfach einer kostenlosen Liste hinzu, die calcoc () und malloc () später beraten wird, um das wiederverwenden freigegebene Blöcke. Es gibt gute Gründe für diesen Designansatz.

Auch wenn ein kostenloser () den Speicher an das System zurücksenden möchte, benötigen Sie mindestens eine zusammenhängende Speicherseite, um den Kernel, um den Kernel tatsächlich zu schützen, um die Region tatsächlich zu schützen, so dass der Loslassen eines kleinen Blocks nur zu einer Schutzänderung führen würde Wenn es der kleinste letzte kleine Block auf einer Seite war.

Operationstheorie

so malloc (3) wird der Erinnerung vom Kernel, wenn er es braucht, letztendlich in Einheiten diskreter Seitenmultiples. Diese Seiten sind unterteilt oder konsolidiert, da das Programm erfordert. Malloc und kostenlose Zusammenarbeit, um ein Verzeichnis aufrechtzuerhalten. Sie kopieren nach Möglichkeit benachbarte freie Blöcke, um große Blöcke bereitzustellen. Das Verzeichnis kann mit dem Speicher in freier Verfügung, um eine verknüpfte Liste zu verwenden. (Die Alternative ist ein bisschen mehr gemeinsam genutzter Speicher und pagingfreundlich, und es beinhaltet das Zeilen von Speicher speziell für das Verzeichnis.) MALLOC und FREE haben wenig, wenn Sie den Zugriff auf einzelne Blöcke durchsetzen, auch wenn ein spezieller und optionaler Debugging-Code erstellt wird das Programm.


1. Die Tatsache, dass nur sehr wenige Implementierungen des freien () Versuchses, den Speicher an das System zurückzugeben, nicht überhaupt nicht aufgrund der Nachfolger des Implements.

Interaging mit dem Kernel ist viel langsamer als Ein einfacher Ausführen des Bibliothekscodes, und der Nutzen wäre klein. Die meisten Programme verfügen über einen stationären oder steigenden Memory-Footprint, sodass die analysierende Zeit, die die Analyse des Haufens auf der Suche nach dem rückverkehrbaren Speicher analysiert, vollständig verschwendet. Andere Gründe beinhaltet die Tatsache, dass die interne Fragmentierung Seiten-ausgerichtete Blöcke unwahrscheinlich ist, und es ist wahrscheinlich, dass das Zurückgeben eines Blocks, dass Fragment auf beiden Seiten fragmentiert wird. Schließlich werden die wenigen Programme, die große Speichermengen zurückgeben, wahrscheinlich MALLOC () umgehen und ohnehin einfach und kostenlose Seiten zuweisen.

Allgemein frei () gibt den physischen Speicher nicht an das Betriebssystem zurück, sie werden immer noch in der virtuellen Speicher Ihres Prozesses abgebildet.Wenn Sie einen großen Chunk-Speicher zuordnen, kann LIBC es von mMAP () zuordnen.Wenn Sie es kostenlos kostenlos, kann LIBC den Speicher an das Betriebssystem von MUNMAP () freigeben, in diesem Fall wird angezeigt, dass Ihre Speicherverwendung heruntergefahren wird.

Wenn Sie also den Speicher an das Betriebssystem explizit freigeben möchten, können Sie MMAP () / MunMap () verwenden.

Wenn du free() Speicher wird es an den Speicherpool der Standard-C-Bibliothek und nicht an das Betriebssystem zurückgegeben.In der Vision des Betriebssystems, wie Sie es durchschauen top, „benutzt“ der Prozess diesen Speicher immer noch.Innerhalb des Prozesses hat die C-Bibliothek den Speicher berücksichtigt und könnte denselben Zeiger von zurückgeben malloc() in der Zukunft.

Ich erkläre es noch einmal mit einem anderen Anfang:

Während Ihrer Anrufe bei malloc, stellt die Standardbibliotheksimplementierung möglicherweise fest, dass dem Prozess nicht genügend vom Betriebssystem zugewiesener Speicher zur Verfügung steht.Zu diesem Zeitpunkt führt die Bibliothek einen Systemaufruf durch, um mehr Speicher vom Betriebssystem für den Prozess zu erhalten (z. B. sbrk() oder VirtualAlloc() Systemaufrufe unter Unix bzw. Windows).

Nachdem die Bibliothek zusätzlichen Speicher vom Betriebssystem angefordert hat, fügt sie diesen Speicher zu ihrer Speicherstruktur hinzu, aus der zurückgekehrt werden kann malloc.Spätere Anrufe bei malloc wird diesen Speicher verwenden, bis er aufgebraucht ist.Anschließend bittet die Bibliothek das Betriebssystem um noch mehr Speicher.

Wenn du free Speicher, die Bibliothek gibt den Speicher normalerweise nicht an das Betriebssystem zurück.Dafür gibt es viele Gründe.Ein Grund dafür ist, dass der Autor der Bibliothek geglaubt hat, Sie würden anrufen malloc wieder.Wenn Sie nicht anrufen malloc Auch hier wird Ihr Programm wahrscheinlich bald enden.In beiden Fällen bringt es keinen großen Vorteil, den Speicher an das Betriebssystem zurückzugeben.

Ein weiterer Grund dafür, dass die Bibliothek den Speicher möglicherweise nicht an das Betriebssystem zurückgibt, besteht darin, dass der Speicher vom Betriebssystem in großen, zusammenhängenden Bereichen zugewiesen wird.Es kann nur zurückgegeben werden, wenn ein gesamter zusammenhängender Bereich nicht mehr verwendet wird.Das Muster des Anrufens malloc Und free möglicherweise nicht den gesamten Einsatzbereich abdeckt.

Zwei Probleme:

  • In make_cache_db(), die Linie

    for (int i=0; i = n; i++)
    

    sollte wohl lesen

    for (int i=0; i<n; i++)
    

    Andernfalls weisen Sie nur eine zu cache_db_s Knoten.

  • Die Art und Weise, wie Sie zuweisen cache_db In make_cache_db() Scheint fehlerhaft zu sein.Es scheint, dass Ihre Absicht darin besteht, einen Zeiger auf das erste Element der verknüpften Liste zurückzugeben.Sondern weil Sie eine andere Aufgabe übernehmen cache_db In jeder Iteration der Schleife geben Sie am Ende einen Zeiger auf zurück zuletzt Element der Liste.

    Wenn Sie die Liste später mit freigeben free_cache_db(), führt dies zu einem Speicherverlust.Derzeit wird dieses Problem jedoch durch den im vorherigen Aufzählungspunkt beschriebenen Fehler verdeckt, der dazu führt, dass Sie Listen nur mit der Länge 1 zuweisen.

Unabhängig von diesen Fehlern ist der von aix angesprochene Punkt sehr gültig:Die Laufzeitbibliothek muss nicht alle zurückgeben free()d Speicher an das Betriebssystem.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top