快速好奇的问题,内存分配地址是由语言编译器选择的,还是选择所询问内存地址的操作系统?
这是对虚拟内存的疑问,它可以快速解释为“让进程认为他拥有所有内存”,但是在64位体系结构中会发生什么,如果进程只有48位用于内存地址想要更高的地址?
让我们说你做了一个int a = malloc(sizeof(int));
并且你之前的系统调用没有剩余内存,因此你需要向操作系统询问更多内存,编译器是确定分配这个变量的内存地址的编译器,或者只是向操作系统询问内存并将其分配给它返回的地址?
答案 0 :(得分:2)
它不是编译器,特别是因为这是动态内存分配。在您实际执行程序之前完成编译。
静态变量的内存预留在编译时发生。但静态内存分配将在用户定义Main之前在启动时发生。
静态变量可以在可执行文件本身中给出空间,然后将内存映射到进程地址空间。这只是少数几次(?)我可以想象编译器实际上“决定”地址。
在动态内存分配期间,程序会向操作系统询问一些内存,而操作系统会返回内存地址。然后将该地址存储在指针中,例如。
答案 1 :(得分:0)
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)
{}
实用的内存分配器不依赖于这样的静态内存池,而是调用操作系统为它们提供新映射的内存。
正确的思考方式是:你不知道你将从malloc()
获得什么特定的指针。如果您使用非零参数调用malloc()
,则只能知道它是唯一的并指向正确对齐的内存。就是这样。