快速好奇的問題,內存分配地址是由語言編譯器選擇還是選擇內存地址的操作系統?操作系統內存分配地址
這是來自對虛擬內存的懷疑,它可以很快地解釋爲「讓流程認爲他擁有所有內存」,但是在64位體系結構中會發生什麼情況,只有48位用於內存地址進程想要更高的地址?
假設你做了int a = malloc(sizeof(int));
,並且你沒有留下以前系統調用的內存,所以你需要向操作系統請求更多的內存,編譯器是決定分配這個變量的內存地址還是編譯器只需向操作系統請求內存,然後將其分配給由它返回的地址?
快速好奇的問題,內存分配地址是由語言編譯器選擇還是選擇內存地址的操作系統?操作系統內存分配地址
這是來自對虛擬內存的懷疑,它可以很快地解釋爲「讓流程認爲他擁有所有內存」,但是在64位體系結構中會發生什麼情況,只有48位用於內存地址進程想要更高的地址?
假設你做了int a = malloc(sizeof(int));
,並且你沒有留下以前系統調用的內存,所以你需要向操作系統請求更多的內存,編譯器是決定分配這個變量的內存地址還是編譯器只需向操作系統請求內存,然後將其分配給由它返回的地址?
它不會是編譯器,尤其是因爲這是動態內存分配。編譯完成之前,你真的執行你的程序。
靜態變量的內存預留髮生在編譯時。但是靜態內存分配將在用戶定義Main之前在啓動時發生。
靜態變量可以給出可執行文件本身的空間,這將被內存映射到進程的地址空間。這只是少數幾次之一(?)我可以將編譯器實際上映射到地址上的「決定」。
在動態內存分配過程中,你的程序會向操作系統詢問一些內存,它是返回內存地址的操作系統。例如,這個地址被存儲在一個指針中。
在C/C++的動態存儲器分配簡單地通過運行時庫函數來完成。只要他們的行爲符合標準,這些功能就可以隨心所欲地完成。一個簡單的實現的兼容,但沒用malloc()
看起來是這樣的:
void * malloc(size_t size) {
return NULL;
}
的要求是比較寬鬆 - 指針已被適當地對齊,並且指針必須是唯一的,除非他們之前free()d
了。你可能有一個相當愚蠢的,但有點可移植,絕對不是線程安全的內存分配器完成下面的方式。在那裏,地址來自編譯器決定的池。
#include "stdint.h"
// 1/4 of available address space, but at most 2^30.
#define HEAPSIZE (1UL << (((sizeof(void*)>4) ? 4 : sizeof(void*)) * 2))
// A pseudo-portable alignment size for pointerŚbwitary types. Breaks
// when faced with SIMD data types.
#define ALIGNMENT (sizeof(intptr_t) > sizeof(double) ? sizeof(intptr_t) : siE 1Azeof(double))
void * malloc(size_t size)
{
static char buffer[HEAPSIZE];
static char * next = NULL;
void * result;
if (next == NULL) {
uintptr_t ptr = (uintptr_t)buffer;
ptr += ptr % ALIGNMENT;
next = (char*)ptr;
}
if (size == 0) return NULL;
if (next-buffer > HEAPSIZE-size) return NULL;
result = next;
next += size;
next += size % ALIGNMENT;
return result;
}
void free(void * ptr)
{}
實用的內存分配不依賴於這樣的靜態內存池,而是調用OS爲他們提供新的映射內存。
正確的思考方式是:你不知道什麼特定的指針你將從malloc()
得到。只有當您調用malloc()
並帶有非零參數時,才能知道它是唯一的並指向正確對齊的內存。就這樣。