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