1、exit、_exit、_Exit函数
在头文件stdlib.h中定义
void exit(int status);
void _exit(int status);
void _Exit(int status);
_exit、_Exit函数直接进入内核,而exit函数总是先执行终止处理程序(exit handler),再关闭所有打开的流后,才进入内核。这三个函数的参数是退出码。
可以调用atexit函数来设置终止处理程序,且可以设置多个,这些终止处理函数的调用次序与设置次序正好相反,并且一个函数如果被设置多次,也将被调用多次。该函数原型如下
int atexit(void (*func)(void));
2、C程序的存储空间分布
C程序由以下部分组成:
正文段:CPU执行的代码
初始化数据段:即数据段,包含程序中明确赋初值的全局、静态变量。
非初始化数据段:也叫bss段,该段中的内容由程序开始执行之前全部赋为0或空指针,包含未明确赋初值的全局、静态变量。
栈:自动变量了。
堆:动态分配了,位于初始化数据段和栈之间。
一种典型的内存布局如下
高地址 ……命令行参数和环境变量
……栈
……
未使用的地址空间
……
……堆
……未初始化的数据(由exec初始化为0)
……初始化的数据(由exec从程序文件读入)
低地址 ……正文(由exec从程序文件读入)
栈向低地址增长,堆向高地址增长。只有正文段和初始化数据段才存放在程序文件中。其它还包含符号表段、调试信息段和动态链接库表段等等,这些部分并不装载到进程执行的程序映像中。
用size命令可以查看程序的正文段、数据段和bss段的长度。
3、环境变量
在头文件stdlib.h中定义
char* getenv(const char *name);
int putenv(char *str);
int setenv(const char *name, const char *value, int rewrite);
int unsetenv(const char *name);
getenv的参数name所指的环境变量若不存在,则返回NULL,否则返回value的指针。
putenv的参数是“name=value”形式的字符串,且直接将str的地址用作环境变量的地址,需要注意,参数str不能是在栈上的。
setenv如果name所指的环境变量已经存在,若rewrite非0,则先删除,后再写入;若rewrite为0,则不删除不写入,也不出错。
unsetenv删除name的定义,不存在也不出错。
4、 函数间跳转
在头文件setjmp.h中声明了一下两个函数来实现函数间跳转
int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);
要在函数间跳转,env通常定义为全局的。
setjmp设置函数跳转返回到的地方。
longjmp实现函数跳转,env指定返回地址,val指定返回值,可以从多个地方返回到某一相同点。