当启动 C 程序时,它如何向操作系统询问静态变量的足够内存空间? 在运行时如何向操作系统内存空间询问自动变量?
我还想知道它在执行后如何释放这些内存空间。
请尽量做到最准确。如果操作系统的解释不同,请优先选择类似UNIX的操作系统。
答案 0 :(得分:2)
类Unix系统上的内存分配是通过使用sbrk()
和mmap()
API调用操作系统完成的。
sbrk()
用于扩大“数据段”,这是一个连续的(虚拟)地址范围。 mmap()
在许多现代系统中用作对此的补充,因为它可以分配块,以后可以独立解除分配(意味着sbrk()
可能不会出现“漏洞”)。 / p>
在C中,您有malloc()
作为内存分配的面向用户的API。您可以在此处详细了解如何映射到我之前提到的低级函数:How are malloc and free implemented?
答案 1 :(得分:2)
静态变量位于代码后面的BSS段中。自动变量位于进程虚拟内存末尾的堆栈中。两者都是在编译时定义的。然后在程序启动时创建内存布局。 brk(),sbrk()和mmap()可以在运行时操作虚拟内存(特别是堆)(例如使用malloc()/ free())但这些函数与静态和自动变量无关!
答案 2 :(得分:2)
全局变量和具有静态生命周期的变量通常存储在由操作系统的可执行加载程序设置的数据段中。
这个加载器可能会这样,@ John Zwinck在Unix上说的。在Windows上有VirtualAlloc,例如,它也可以用来在另一个程序的地址空间中分配内存。
局部变量通常存储在所谓的堆栈中。堆栈上的分配非常快,因为它们通常只包含堆栈指针寄存器的修改(sp,esp,x86处理器系列上的rsp)。因此,当你有一个int(大小:4个字节)时,当堆栈向下增长时,寄存器将简单地减少4。在范围的末尾,堆栈寄存器的旧状态被恢复。
这也使得堆栈溢出很危险,你可以覆盖不应修改的堆栈上的其他变量,比如函数调用的返回地址。
动态变量是使用malloc(C)或new(C ++)或任何特定于操作系统的分配函数分配的变量。这些放在所谓的堆上。它们一直存在,直到使用free / delete / os-specific-deallocator清除它们或程序退出(在这种情况下,一个理智的操作系统负责清理)。
同样,动态分配是三者中最慢的,因为它需要调用操作系统。