郑州品牌营销网站建设,电子商务主要学的是什么,营销型网站北京,做买东西的网站要多少钱在程序中我们访问的内存地址都是从物理内存上映射而来的虚拟地址#xff0c;假设我们使用的计算机实际物理内存#xff08;PM#xff09;只有1GB#xff0c;而Linux中执行着三个进程#xff0c;Linux会将PM中的某段内存映射成三段4G大小相同的虚拟内存#xff08;VM… 在程序中我们访问的内存地址都是从物理内存上映射而来的虚拟地址假设我们使用的计算机实际物理内存PM只有1GB而Linux中执行着三个进程Linux会将PM中的某段内存映射成三段4G大小相同的虚拟内存VM让每个进程都认为得到了需要的完整内存
进程内存布局 在虚拟内存中内存是被分配给不同的部分的具体每部分存储的内容如下图 对该图做几点说明
1栈中的环境变量和命令行参数在程序一开始运行之时就被固定在了栈底即紧挨着内核的地方且在进程在整个运行期间不再发生变化假如进程运行时对环境变量的个数或者值做了修改则为了能够容纳修改后的内容新的环境变量将会被拷贝放置到堆中。
2栈还有一个名称叫做“堆栈”这是中文比较奇葩的地方“堆栈”跟“堆”没有半毛钱关系。
3栈和堆都是动态变化的分别向下和向上增长大小随着进程的运行不断变大变小。
4静态数据指的是所有的全局变量以及static 型局部变量。
5数据段的大小在进程一开始运行就是固定的其中.rodata存放程序中所有的常量.data存放所有的静态数据而如果静态数据未被初始化则程序刚开始运行时系统将会自动将他们统统初始化为0然后放置在.bss段中这么做的原因是要节省磁盘存储空间由于未初始化的静态数据在运行时一概会被初始化为0因此在程序文件中就没有必要保存任何未初始化的变量的值了。
6如果没有一个极具说服力的理由我们应该尽量避免使用静态数据因为滥用静态数据至少有两个缺点第一静态数据的生命周期跟整个进程相当也就是说不管你什么时候需要用到他们他们在进程一开始运行的时候就已经存在了而且就算你不再需要他们在进程完全退出之前他们都不会释放会无条件地一直占用内存。第二静态数据中的全局变量是一种典型的共享资源尤其在多线程程序中共享资源是滋生“竞态”的温床详见5.x.x小节实在没办法要在多线程程序在使用全局变量必须仔细地使用各种同步互斥手段保护他们而不是简单粗暴地胡乱使用。
7用户代码所在的.text段也称为正文段.text是一个默认的名称他将会囊括用户定义的所有的函数代码实际上我们可以将某些指定的函数放置到自己指定段当中去比如在程序代码中有一段音乐数据我们可以将此段数据放置在一个.mp3的代码段当中详见2.6.3小节而.init段是存放的系统初始化代码这部分代码之所以要放置在.init段是因为这个段当中的代码默认只会被执行一遍初始化只能执行一遍完成任务之后所占据的内存会被立即释放以便节省系统资源因此我们自己定义的函数如果也是在进程开始之初只执行一遍就不再需要那么也可以将之放置在该段中。 堆heap 堆内存被称为内存中的自由区这是一个非常重要的区域因为在此区定义的内存的生命周期我们是可以控制的域对比其他区域的内存则不然比如栈内存栈的特点就是临时分配临时释放一个变量如果是局部变量他就会被定义在栈内存中一旦这个局部变量所在的函数退出不管你愿不愿意该局部变量也就会被立即释放再如静态数据他们都被存储在数据段如前所述这些变量将一直占用内存直到进程退出为止。 堆内存的生命周期是从malloc /calloc /realloc 开始到free 结束其分配和释放完全由我们开发者自定义这就给了我们最大的自由和灵活性让程序在运行的过程当中以最大的效益使用内存。 对堆操作的函数介绍如下 堆最大的特点是自定义其生命周期除了调用free不会因为所在函数退出而释放
此处增加一个示例表明使用方法
#include stdio.h
#include stdlib.hint *heap_array(int *old_ptr,int n);
void show(int *ptr);int main(int argc, char const *argv[])
{int n , *p (int*)malloc(1 * sizeof(int));//分配一块int类型大小的内存p[0] 1;while (1){if(scanf(%d,n) 0)//输入非数字则退出break;p heap_array(p , n);//输入数字则扩展内存并将数字填入最新的堆show(p);}free(p);return 0;
}int *heap_array(int *old_ptr,int n)
{int size,*new_ptr;size old_ptr[0]1;new_ptr (int*) realloc(old_ptr , size * sizeof(int));new_ptr[0] size;new_ptr[size - 1] n;return new_ptr;
}void show(int *ptr)
{printf(--- );for (int i 1; i ptr[0]; i){printf(%d ,ptr[i]);}printf(---\n);}