2014-01-29 6 views
12

Wie arbeiten realloc tatsächlich im Hintergrund? Wenn nicht genügend Speicher vorhanden an der alten Stelle tut diese ein zwei/viele Speicherblöcke und einen Zeiger auf den Hinweis und andere sind intern verbunden mit jeder andere oder die alte Region kopiert in neue Stelle Zuweisung wo genug Speicher ist verfügbar und Zeiger aktualisiert auf neue Adresse und löscht den alten Speicher?Wie `realloc` tatsächlich im Hintergrund arbeiten?

Und ist das realloc ist Compiler/OS abhängig oder unabhängig?

Antwort

11

realloc versucht, den verfügbaren Speicherbereich zu erweitern, wenn genügend Speicher dahinter auf dem Heap verfügbar ist. Wenn nicht, dann ist es gleich malloc ein Block der neuen Größe, memcpy Ihre Inhalte dort, free der alte Block. Dies ist unabhängig von Betriebssystem und Compiler und hängt von der Implementierung von libc ab, mit der Sie verknüpfen.

Zu einem ähnlichen Hinweis: mremap/MREMAP_MAYMOVE (verfügbar auf modernen Linux) wird versuchen, Ihre virtuelle Zuordnung um die angeforderte Größe zu erweitern. Wenn dies nicht möglich ist, wird das Mapping auf eine neue virtuelle Adresse verschoben, hinter der genügend VM-Speicherbereich vorhanden ist, und dann das Mapping erweitern. Dies ist sehr schnell, wenn Sie häufig große Zuordnungen in der Größe ändern, da kein physisches Kopieren ausgeführt wird.

+3

+1 für 'mremap/MREMAP_MAYMOVE'. – edmz

2

Wenn der alte Zeiger nicht in der Größe geändert werden kann, wird ein neuer zugewiesen, der Inhalt wird kopiert und der alte wird freigegeben.

8

Eine Implementierung von realloc() kann in etwa wie folgt aussehen:

void * realloc(void *ptr, size_t size) 
{ 
    // realloc() on a NULL pointer is the same as malloc(). 
    if (ptr == NULL) 
     return malloc(size); 

    size_t oldsize = malloc_getsize(ptr); 

    // Are we shrinking an allocation? That's easy. 
    if (size < oldsize) { 
     malloc_setsize(ptr, size); 
     return ptr; 
    } 

    // Can we grow this allocation in place? 
    if (malloc_can_grow(ptr, size)) { 
     malloc_setsize(ptr, size); 
     return ptr; 
    } 

    // Create a new allocation, move the data there, and free the old one. 
    void *newptr = malloc(size); 
    if (newptr == NULL) 
     return NULL; 
    memcpy(newptr, ptr, oldsize); 
    free(ptr); 
    return newptr; 
} 

Bitte beachte, dass ich mit malloc_ hier beginnen mehrere Funktionen mit Namen nenne. Diese Funktionen existieren (nach bestem Wissen) in keiner Implementierung; Sie sind als Platzhalter gedacht, aber der Zuordner führt diese Aufgaben tatsächlich intern aus.

Da die Implementierung von realloc() von diesen internen Tools abhängt, ist ihre Implementierung vom Betriebssystem abhängig. Die Schnittstelle ist jedoch universell.

+0

danke für die saubere lösung .. –