以类Unix环境下的程序运行为例,说明C程序的运行过程和内存分配,windows环境下原理一致,但实现细节会有区别,所以首先我们要明白:程序的内存布局(Program Memory Layout)是与操作系统相关的。尽管技术的发展非常迅速,但这些原理性的东西始终是基础。
类Unix环境下,C程序在执行main函数之前(符合标准的main函数,其形参还包括有环境变量,因为我们执行程序都是在Shell下面),会先利用操作系统提供的系统调用和exec函数来进行一些初始化操作,最后才转移到main函数体内。整个程序在进行装载后在内存中运行,使用逻辑地址来进行表示,通常是由以下的一些区域构成(段的概念详见《微机原理》中的叙述,与内存的管理方式有关):
文本段(text segment):例如CPU执行的机器指令,通常文本段是只读性质的,还有文字常量区,例如字符串常量会放在该段。
简单数据段(initialized data segment):初始化的全局变量或者初始化的静态变量。
bss段(uninitialized data segment):未初始化的全局变量等。
栈(stack):局部变量,以及函数形参等,强调变化。
堆(heap):动态内存,需要由程序自己处理释放问题。
下面的程序在main函数退出之前运行一段代码,通过了解atexit函数可以理解main函数在类Unix操作系统中的标准定义(windows原理一致):
#include <stdio.h>
#include <stdlib.h>
void bye(void)
{
printf("byebye!\n");
}
int main(int argc, char *argv[])
{
(void)atexit(bye);
return (0);
}
参考资料:
[1] 《Advanced Programming in the UNIX® Environment: Second Edition》,W. Richard Stevens,Stephen A. Rago
[2] http://linuxgazette.net/issue84/hawk.html
[3] http://linux.die.net/man/3/atexit