Warum zuteilen malloc eine unterschiedliche Anzahl von Bytes als angefordert?
Frage
Ich habe dieses Stück Code
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
int main(){
void *a, *b;
a = malloc(16);
b = malloc(16);
printf("\n block size (for a): %p-%p : %li", b, a, b-a);
a = malloc(1024);
b = malloc(1024);
printf("\n block size (for a): %p-%p : %li", b, a, b-a);
}
Sollte dies nicht die letzte zugeordnet Blockgröße drucken (16 oder 1024)? Es stattdessen druckt 24 und 1032, so dass die Menge an Speicher zugewiesen scheint 8 zusätzliche Bytes zu haben.
Mein Problem ist (vor diesem Testfall machen), dass ich malloc()
in einer Funktion (1024 Byte) zu tun, und gibt die zugewiesenen Ergebnis. Wenn die Blockgröße auf die Funktion Rückkehr Überprüfung erhalte ich 516 Blöcke ... und ich verstehe nicht, warum. Ich denke, dies könnte der Grund für die Speicherfehler, die nach tut einige Verarbeitung auf dem zugewiesenen Puffer auftreten:)
Bearbeiten: Ich habe Wie kann ich die Größe eines Arrays von einem Zeiger in C? und scheint dasselbe zu fragen, sorry für reposting.
Ich habe mein Beispiel zu meinem spezifischere Code nochmals gemacht:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
short int * mallocStuff(long int number, short int base){
short int *array;
int size=1024;
array=(short int*)calloc(1,size);
//array=(short int*)malloc(size);
return array;
}
int main(){
short int **translatedArray;
translatedArray=malloc(4*sizeof(short int));
int i;
for(i=0;i<4;i++){
translatedArray[i]=mallocStuff(0,0);
if(i>0)
printf("\n block size (for a): %p-%p : %i",
translatedArray[i], translatedArray[i-1], translatedArray[i]-translatedArray[i-1]);
}
return 0;
}
Und der Ausgang ist
block size (for a): 0x804a420-0x804a018 : 516
block size (for a): 0x804a828-0x804a420 : 516
block size (for a): 0x804ac30-0x804a828 : 516
Nach der oben genannten Post, die größer als 1024. Am ist ich falsch?
Lösung
Sie haben einen Fehler. Statt:
translatedArray=malloc(4*sizeof(short int));
Sie sollten
translatedArray=malloc(4*sizeof(short int*));
Beachten Sie die fehlende Zeiger in Ihrem Code. Ich vermute, das ist, wo Ihr beobachtete Verhalten ergibt sich aus.
Sie auch, dass 0x804a420 - 0x804a018 = 1032
bemerken, nicht 516
. Die Formel translatedArray[i] - translatedArray[i - 1]
gibt Ihnen die Anzahl der Elemente (kurz Ints, oder einfacher, Shorts) zwischen den beiden Adressen, nicht die Anzahl der Bytes .
Andere Tipps
Als erstes macht Malloc keine Garantie, dass zwei aufeinanderfolgende malloc Anrufe aufeinanderfolgende Zeiger zurück.
Zweitens, je nach Ihrer spezifischen Architektur, unterschiedliche Ausrichtung Regeln gelten; manchmal könnte man für ein einzelnes Byte fragen, aber die Architektur bevorzugt Zuweisungen auf 8- oder 4-Byte-Intervallen.
Drittens malloc braucht einige Overhead zu speichern, wie groß der zugeordnete Block ist, etc.
Sie keine Annahmen darüber, was malloc tut Vergangenheit, was die Dokumentation sagt!
Die malloc
Funktion ordnet immer etwas mehr als man sich wünschen, um einige Buchhaltungsinformationen zu speichern. Nach allem, wenn Sie free()
aufrufen muss es wissen, wie groß der Block ist.
Auch im Allgemeinen malloc
Implementierungen werden die gewünschte Größe bis zum nächsten Vielfachen von 8 oder 16 oder einer anderen Rund ish Zahl gerundet werden soll.
Aktualisieren : Die wirkliche Antwort auf Ihre Frage liegt in der Nutzung des short int
Typs. Wenn Pointer-Arithmetik zu tun (Subtraktion) zwischen typisierten Zeigern, C und C ++, um den Unterschied in der Nummer zurück die Dinge deuteten auf. Da Sie auf short int
verweisen, die zwei Bytes groß ist, kehrte der Wert ist die Hälfte von dem, was man erwartet.
Auf der anderen Seite, malloc
weist immer eine bestimmte Anzahl von Bytes , egal, was das Ergebnis werfen danach auf. Versuchen Sie folgendes:
array=(short int*)malloc(sizeof(short int) * size);
Es gibt keine Garantien, dass zwei malloc Anrufe zurückkehren Blöcke genau zusammengepackt - in der Tat gibt es keine Garantien über das Ergebnis überhaupt, mit der Ausnahme, dass, wenn es nicht NULL ist es zu einem Block mindestens so groß wie der Punkt angefordert werden.
Intern meisten mallocs Halten Daten arbeiten, um sie zu verwalten den Haufen zu helfen. Zum Beispiel könnte dieses 8 Bytes zwei Zeiger enthält - einen Hinweis auf den nächsten Block und einen auf den vorherigen Block. Ich weiß nicht, was diese 8 Bytes sind, weil Sie nicht erwähnt, welches Betriebssystem Sie laufen auf, aber es ist völlig normal für malloc für sich etwas Speicher zu verwenden, hinter den Kulissen.
Einige Verteilern (zB Fenster), um eine Bibliotheksfunktion bieten Blockgröße eines Zeiger gegeben zu entdecken, aber manche nicht, da es ein eher esoterisches Merkmal ist.
Was malloc zurückkehrt, hängt von der Implementierung von malloc und der Architektur. Wie andere schon gesagt haben, werden Sie garantiert zumindest die angeforderte Menge an Speicher, oder NULL zu erhalten. Dies ist auch, warum manchmal, Sie über das Ende eines Arrays schreiben können, und nicht einen Segmentation Fault erhalten. Es ist, weil Sie tatsächlich einen gültigen Zugriff auf diesen Speicher DO haben, die Sie gerade es nicht wissen.
malloc () wird in der Regel durch Aufteilung der verfügbaren Heap in Blöcken unterschiedlicher Größe realisiert. In Ihrem Fall malloc () gibt 2 aufeinander folgenden 1024 (oder 16) Byte Chunks. Der 8-Byte-Raum, den Sie erwähnen, ist von malloc () verwendet, um Informationen Buchhaltung.
Siehe Doug Lea malloc () impl Notizen hier zu verstehen, was in hinter den Kulissen geht:
Ganz zu schweigen davon, dass es keine Garantie dafür, dass zwei aufeinander folgende Zuteilungen an nebeneinander sein, mit zu beginnen. malloc()
wird es eigener Kopf ist.
Wenn malloc
etwas anderes als null zurückgibt, dann ist der Speicher, dass es zugeordnet wurde für Ihr Programm hat die Größe, die Sie malloc
geben. Unter den Zeiger Differenz zwischen den Rückgabewerten von zwei Differenz nennt einen beliebigen Wert zu malloc
haben könnte und hat nichts (auch wenig) mit der Blockgröße des ersten zugeordneten Block zu tun.
fand ich this..and Prüfung für den Link unten für weitere Informationen.
Allocation
ein Block aus dem freien Pool zugeordnet, indem zunächst die angeforderten Bytes zu einem Index in dem Array bucket Umwandeln Verwendung der folgenden Gleichung:
benötigt = angefordert + 8
Bei Bedarf <= 16, dann Eimer = 0
Bei Bedarf> 16, dann Eimer = (log (erforderlich) / log (2), gerundet auf die nächste ganze Zahl nach unten) - 3
Die Größe jedes Blocks in der Liste durch die Schaufel verankert ist Blockgrße = 2 bucket + 4. Wenn die Liste in den Eimer null ist, Speicher zugewiesen wird, um das Unterprogramm unter Verwendung sbrk Blöcke in die Liste hinzuzufügen. Wenn die Blockgröße kleiner als eine Seite ist, dann wird eine Seite mit dem sbrk Unterprogramm zugeordnet, und die Anzahl von Blöcken erreicht, indem die Blockgrße in die Seitengröße Dividieren der Liste hinzugefügt werden. Wenn die Blockgröße gleich oder größer als eine Seite gleich ist, benötigt Speicher zugeordnet ist, die sbrk Subroutine verwendet, und ein einzelner Block wird für die Schaufel in die freie Liste hinzugefügt. Wenn die freie Liste nicht leer ist, wird der Block an der Spitze der Liste an den Aufrufer zurückgegeben. Der nächste Block auf der Liste, dann wird der neue Kopf.
Bevor der Zeiger die Größe des folgenden Array steht, die ein 32/64 Bit-Integer (weiß nicht, ob mit oder ohne Vorzeichen)
, so dass die Menge des zugewiesenen Speichers scheint 8 zusätzliches Bytes haben? malloc()
Implementierung auf Ihrem System scheint zusätzliches Bytes zuzuteilen Meta-Daten Informationen wie zu erhalten, wie groß Haufen Abschnitt ist, was Adresse beginnt etc info.
Obwohl seine Variiert auf verschiedenen Plattformen.
Auf meinem X86 System, Aufteilung malloc()
min von 17
Bytes, auch wenn ich malloc(0)
bin anfordern.
int main(void) {
int *p = malloc(0);
if(p == NULL) {
/* error handling */
}
printf("%d\n",p[-1]);/ *it prints 17 bytes */
/* some code */
return 0;
}
malloc () kann zusammenhängenden Speicher zuweisen, aber wenn Ihre Berufung malloc () 2 mal und nicht die Speicher zusammenhängend sein zugeteilt erwarten kann durch Subtraktion zweier Zeiger variabls ...
Allerdings zugewiesenen Speicher der virtuelle Speicher ist, die ein Teil der Kernel-Implementierung ist, Speicherverwaltung (VFS) um genau zu sein. Es kann nicht Anwendungsfunktionalität beeinflussen.