Saya memiliki program ac yang terlihat seperti ini
main.c
#include <stdio.h>
#define SOME_VAR 10
static int heap[SOME_VAR];
int main(void) {
printf("%p", heap);
return 0;
}
dan menampilkan ini ketika saya menjalankan program yang dikompilasi beberapa kali
0x58aa7c49060
0x56555644060
0x2f8d1f8e060
0x92f58280060
0x59551c53060
0xd474ed6e060
0x767c4561060
0xf515aeda060
0xbe62367e060
Mengapa selalu berakhir pada 060? Dan apakah array disimpan di heap?
Sunting: Saya di Linux dan ASLR aktif. Saya mengkompilasi program menggunakan gcc
Jawaban:
Alamat berbeda karena ASLR (ramdomization tata letak ruang alamat). Dengan menggunakan ini, biner dapat dipetakan di lokasi yang berbeda di ruang alamat virtual.
Variabelnya
heap
- berbeda dengan namanya - tidak terletak di heap, tetapi dibss
. Offset di ruang alamat karenanya konstan.Halaman dipetakan pada granularity halaman, yaitu 4096 byte (hex: 0x1000) pada banyak platform. Inilah alasannya, mengapa tiga digit hex terakhir dari alamat itu sama.
Ketika Anda melakukan hal yang sama dengan variabel stack , alamat tersebut bahkan dapat bervariasi dalam digit terakhir pada beberapa platform (yaitu linux dengan kernel terbaru), karena stack tidak hanya dipetakan di tempat lain tetapi juga menerima offset acak saat startup.
sumber
heap
ketika tidak ada dalam heap?060
.Jika Anda menggunakan Windows, alasannya adalah struktur PE .
heap
Variabel Anda disimpan di.data
bagian file dan alamatnya dihitung berdasarkan awal bagian ini. Setiap bagian dimuat dalam alamat secara independen, tetapi alamat awalnya adalah kelipatan dari ukuran halaman. Karena Anda tidak memiliki variabel lain, alamatnya mungkin mulai dari.data
bagian, jadi alamatnya akan lebih dari satu ukuran chunk.Sebagai contoh, ini adalah tabel dari Windows versi dikompilasi dari kode Anda: The
.text
seksi yang kode dikompilasi Anda dan.data
berisi Andaheap
variabel. Ketika PE Anda dimuat ke dalam memori, bagian dimuat di alamat yang berbeda dan yang dikembalikan olehVirtualAlloc()
dan akan menjadi beberapa ukuran halaman. Tetapi alamat masing-masing variabel relatif terhadap awal bagian yang sekarang menjadi ukuran halaman. Jadi, Anda akan selalu melihat nomor tetap pada digit yang lebih rendah. Karena alamat relatifheap
dari awal bagian didasarkan pada kompiler, opsi kompilasi, dll. Anda akan melihat nomor berbeda dari kode yang sama tetapi kompiler berbeda, tetapi setiap kali apa yang akan dicetak diperbaiki.Ketika saya mengkompilasi kode, saya perhatikan
heap
ditempatkan pada0x8B0
byte setelah memulai.data
bagian. Jadi setiap kali saya menjalankan kode ini, alamat saya berakhir0x8B0
.sumber
heap
ketika tidak ada dalam heap?Compiler kebetulan diletakkan
heap
pada offset 0x60 byte di segmen data yang dimilikinya, mungkin karena kompiler memiliki beberapa hal lain dalam 0x60 byte pertama, seperti data yang digunakan oleh kode yang memulaimain
rutinitas. Itu sebabnya Anda melihat "060"; itu hanya di mana itu terjadi, dan tidak ada signifikansi yang besar untuk itu.Pengacakan tata letak ruang alamat mengubah alamat dasar yang digunakan untuk berbagai bagian memori program, tetapi selalu melakukannya dalam satuan 0x1000 byte (karena ini menghindari masalah dengan penyelarasan dan masalah lainnya). Jadi Anda melihat alamat berfluktuasi dengan kelipatan 0x1000, tetapi tiga digit terakhir tidak berubah.
Definisi tersebut
static int heap[SOME_VAR];
didefinisikanheap
dengan durasi penyimpanan statis. Implementasi C yang khas menyimpannya di bagian data umum, bukan di heap. "Heap" adalah istilah yang salah untuk memori yang digunakan untuk alokasi dinamis. (Ini keliru karenamalloc
implementasi dapat menggunakan berbagai struktur data dan algoritma, tidak terbatas pada tumpukan. Mereka bahkan dapat menggunakan beberapa metode dalam satu implementasi.)sumber