快速好奇的问题,内存分配地址是由语言编译器选择还是选择内存地址的操作系统?操作系统内存分配地址
这是来自对虚拟内存的怀疑,它可以很快地解释为“让流程认为他拥有所有内存”,但是在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()
并带有非零参数时,才能知道它是唯一的并指向正确对齐的内存。就这样。