3

快速好奇的问题,内存分配地址是由语言编译器选择的,还是操作系统为所要求的内存选择地址?

这是出于对虚拟内存的怀疑,它可以快速解释为“让进程认为他拥有所有内存”,但是如果进程想要更高的内存地址,那么在 64 位架构上会发生什么情况,其中只有 48 位用于内存地址地址?

假设您执行了 aint a = malloc(sizeof(int));并且上一个系统调用没有剩余内存,因此您需要向操作系统请求更多内存,编译器是确定分配此变量的内存地址的人,还是只是向操作系统询问内存并在它返回的地址上分配它?

4

2 回答 2

2

它不会是编译器,特别是因为这是动态内存分配。在您实际执行程序之前,编译已经完成。

静态变量的内存保留发生在编译时。但是静态内存分配将在启动时发生,在用户定义 Main 之前。

静态变量可以在可执行文件本身中分配空间,然后将内存映射到进程地址空间。这只是少数几次(?)我可以想象编译器实际上“决定”了一个地址。

在动态内存分配期间,您的程序会向操作系统请求一些内存,并且操作系统会返回内存地址。该地址然后例如存储在指针中。

于 2012-11-08T22:46:41.667 回答
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()使用非零参数调用,您只能知道它是唯一的并指向正确对齐的内存。就这样。

于 2013-03-01T14:23:48.737 回答