Ich mache einige Beispiel Stack und Heap-Zuweisung auf einem Ubuntu 14.04 VM (Linux 3.13.0-55-generische i686) und ich bin verwirrt von den Speicheradressen für die Heap-Zuweisungen.Was ist der Unterschied zwischen diesen Stack- und Heap-Speicheradressen?
Der unten stehende C-Code weist drei 32-Bit-Bytes ohne Vorzeichen auf dem Stack und drei Zuordnungen auf dem Heap von abnehmenden Größen, 32 Bits, 16 Bits und schließlich 8 Bits zu.
In der Ausgabe unten können wir sehen, dass die Speicheradressen für die drei 32-Bit-Eingänge auf dem Stapel 4 Bits auseinander liegen. uint32_t i ist bei 0xbffd4818 und 4 Adressen später bei 0xbffd481c ist uint32_t j. So können wir hier sehen, dass jedes einzelne Byte des Speichers adressierbar ist und so jeder 4-Byte-Speicherblock 4 Speicheradressen auseinander liegt.
Mit Blick auf die Heap-Zuordnungen können wir sehen, dass uint32_t i_ptr auf 0x99ae008 zeigt und malloc 4 Byte Speicherplatz angefordert, so würde ich erwarten, dass uint16_t j_ptr um 0x99ae00c beginnt, aber es beginnt bei 0x99ae018. Die dritte Heap-Zuweisung für uint8_t k_ptr startet 16 Bytes nach uint16_t i_ptr, die nach uint32_t i_ptr ebenfalls 16 Bytes startet.
- Ist es nur eine Standardeinstellung für das Betriebssystem, dass jede Heapzuweisung 16 Byte auseinander liegt?
- Warum geschieht das unabhängig von der Größe, die ich an malloc übergeben habe?
- Wie können wir 4 Bytes von Informationen zwischen 0x99ae008 und 0x99ae018 passen?
C Quelle:
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
int main() {
register uint32_t ebp asm ("ebp");
printf("0x%x\n", ebp);
register uint32_t esp asm ("esp");
printf("0x%x\n", esp);
uint32_t i;
printf("%p\n", &i);
uint32_t j;
printf("%p\n", &j);
uint32_t k;
printf("%p\n", &k);
uint32_t *i_ptr = malloc(4);
printf("%p\n", i_ptr);
uint16_t *j_ptr = malloc(2);
printf("%p\n", j_ptr);
uint8_t *k_ptr = malloc(1);
printf("%p\n", k_ptr);
free(i_ptr);
free(j_ptr);
free(k_ptr);
return 0;
}
CLI output:
$ gcc -o heap2 heap2.c
$ ./heap2
0xbffd4838 // EBP
0xbffd4800 // ESP
0xbffd4818 // uint32_t i
0xbffd481c // uint32_t j
0xbffd4820 // uint32_t k
0x99ae008 // uint32_t i_ptr
0x99ae018 // uint16_t j_ptr
0x99ae028 // uint8_t k_ptr
Das würde erklären, warum, wenn ich 'malloc (1)' oder 'malloc (2)' den Zeiger immer 16 Bit auseinander, aber was ist mit meinem Aufruf an 'malloc (4)'? j_ptr ist nur 16 Bits im Speicher nach einer 32-Bit-Zuweisung (i_ptr)? – jwbensley
malloc reserviert nicht nur Speicher für die Verwendung durch den Benutzercode, es ist auch Speicher reserviert, um den Heap zu verwalten, zB: so dass free() weiß, was zu tun ist. – Jasen
@jwbensley Ich sehe, dass jede Ausdehnung des zugewiesenen Speichers von 16 Byte unterscheidet: 0x99ae008 // uint32_t i_ptr 0x99ae018 // uint16_t j_ptr 0x99ae028 –