UNIX进程环境

一、C程序的内存布局

==栈==

就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。 

==堆==

就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。 
==自由存储区==

就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。 
==全局/静态存储区==

全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。 
==常量存储区==

这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改

二、进程的中止方式

==进程的正常中止方式有以下5种==
1.   调用exit库函数。该函数通常在正常关闭前会做些清扫工作(例如关闭打开的流),之后再返回kernel。

2.   通过main函数的返回值。实际上,其内在的实现方式相当于:exit(main(argc, argv));

3.   调用 _exit函数 或 _Exit函数。该种方式直接返回kernel,不做任何的清扫工作。只不过前者属于系统调用,后者属于库函数。

4.   进程的最后一个线程结束返回。

5.   进程的最后一个线程调用 pthread_exit函数。

==以下是进程的非正常中止方式==

6.  调用abort函数。

7.  接收到一个信号。

8.  对最后一个线程的cancellation request进行响应。

三、登记终止处理程序
有时候,我们希望在进程结束时,能够做一些额外的操作,例如资源回收等,我们可以通过atexit函数进行注册,其声明如下:
  1. int atexit(void (*func)(void));  

每个进程可以利用这个函数注册至少32个函数(根据实现不同而不同),这些被注册的函数将被exit函数自动调用,调用顺序与登记顺序相反。exit 函数会首先调用这些注册了的函数,然后关闭所有打开了的流,最后才返回kernel。如果我们调用了exec系列的函数,那么,任何注册了的结束处理函数都将被清除。

四、非局部跳转(setjmp和longjmp)

非局部的意思不是想goto语句那样在一个函数内部实施跳转,而是在栈上跳过若干调用帧,返回到当前函数调用路径上的某一个函数。例如,A调用B,B调用C,可以从C直接返回到B。

#include<setjmp.h>
int setjmp(jmp_buf env);//若直接调用返回0;从longjmp调用返回val
void longjmp(jmp_buf env, int val);

考虑一个问题,longjmp返回时,各个变量是否可以回滚到setjmp之前的值?P200页的例子说明longjmp在调用后,自动变量、全局变量、寄存器变量、静态变量和volitile变量的不同情况:

全局变量、static、volatile变量不受优化的影响,他们会恢复到setjmp之前的值,普通变量和寄存器变量会编程longjmp时的值。

六、内存动态分配

==在堆上分配==

void *malloc(size_t size);//分配指定字节数目的存储区,初始值不定
void *calloc(size_t nobj, size_t size);//分配nobj*size大小的空间,每一位都初始化为0
void *realloc(void *ptr, size_t newsize);//更改分配区域的长度,当原存储区没有足够空间时,存储区可能会移动位置,所以不应当使任何指针指向该区域。
void *free(void *ptr);//释放ptr指向的存储空间,被释放的空间通常被送入可用内存池中,而不返回给内核。

==在栈上分配==
void *alloc(size_t size);//在栈上分配内存,不用担心内存释放的问题,但是如果在函数内部使用此函数分配的内存会随着函数接触释放。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值