`

C 存储及环境

阅读更多
    C 程序一般是由下列几部分组成:
    (1)正文段。这是由 CPU 执行的机器指令部分,它通常是可共享的,所以即使是频繁执行的程序(如文本编辑器、C 编译器和 shell 等)在存储器中也只有一个副本。另外,正文段通常是只读的,以防止程序由于意外而修改其指令。
    (2)初始化数据段(简称数据段)。它包含了程序中被明确地赋初值的全局变量等。
    (3)未初始化数据段(也称 bss 段,即“由符号开始的块”(block started by symbol))。函数外的未被初始化声明的变量就被存放在这里。程序开始前,内核将此段中的数据初始化为 0 或空指针。
    (4)栈。自动变量及函数每次调用时所需保存的信息(如返回地址、调用者的环境信息等)都存放在栈中。注意,栈的增长方向一般是从高地址往低地址方向增长的。
    (5)堆。主要用于动态存储分配,一般位于未初始化数据段和栈之间。
    下图是这些段的一种典型存储空间布局。

    从图中可知,未初始化数据段的内容并不存放在磁盘程序文件中,因为内核在程序开始运行前将它们都设置为 0。需要存放在磁盘程序文件中的只有正文段和初始化数据段。
    实际上,编译好的可执行程序中还有若干其他类型的段,如包含符号表的段、包含调试信息的段以及包含动态共享库链接表的段等,不过它们并不装载到进程执行的程序映像中。
    size 命令可报告正文段、数据段和 bss 段的长度(以字节为单位)。如:
$ size /usr/bin/cc /bin/sh
  text    data    bss    dec      hex    filename
346919    3576    6680   357175   57337  /usr/bin/cc
102134    1776    11272  115182   1c1ee  /bin/sh

    其中第 4 列和第 5 列分别是以十进制和十六进制表示的前 3 段的总长度。

    ISO 说明了 3 个用于存储空间动态分配的函数。
#include <stdlib.h>
void *malloc(size_t size);
void *calloc(size_t nobj, size_t size);
void *realloc(void *ptr, size_t newsize);
                      /* 返回值:若成功,都返回非空指针;否则,都返回 NULL */
void free(void *ptr);

    这 3 个函数返回的指针都是适当对齐的,可用于任何数据对象。其中 malloc 分配指定字节数的存储区,其中的初始值不确定;calloc 为指定数量指定长度的对象分配存储空间,其中的每一位都初始化为 0;realloc 可增加或减少以前分配区的长度。当增加长度时,可能需要将以前分配区的内容移到另一个足够大的区域,以便在尾端提供增加的存储区,而新增区域内的初始值则不确定。realloc 的 newsize 参数是存储区的新长度,当 ptr 是空指针时,realloc 的功能就如同 malloc。free 函数可用来释放 ptr 指向的存储空间,以便以后再分配。
    这些分配例程通常用 sbrk 系统调用实现,该系统调用可以扩充或缩小进程的堆。但是大多数 malloc 和 free 的实现都不减小进程的存储空间。释放的空间可供以后再分配,但将它们保持在 malloc 池中而不返回给内核。一般所分配的存储空间都比所要求的要稍大一些,额外的空间会用来记录管理信息,比如分配块的长度、指向下一个分配块的指针等。因此在动态分配的缓冲区前或后进行写操作极有可能会改写另一块的管理记录信息。另外,释放一个已经释放了的块或者释放不是由 alloc 类函数分配的块等都有可能导致致命性的错误。而如果不释放不再使用的空间,则会使进程地址空间长度慢慢增加,直至不再有空闲空间,这被称为泄漏(leakage)。这会导致过度的换页开销,从而造成性能下降。

    每个程序都接收到一张环境表,它是一个字符指针数组,其中每个指针都包含一个指向以 null 结束的 C 字符串的地址,全局变量“extern char **environ”则包含了该指针数组的地址,通常称 environ 为环境指针,指针数组为环境表,其中各指针指向的字符串为环境字符串。例如,一个以 5 个字符串组成的环境看起来大致如下图所示。

    main 函数在大多数 UNIX 系统上的原型是这样的:
        int main(int argc, char **argv[], char *envp[]);
    其中第三个就是环境表地址。不过因为该参数比起 environ 也没有带来多少益处,因此 POSIX.1 也规定应使用 environ 而不使用第 3 个参数。通常用 getenv 和 putenv 等函数来访问和设置特定的环境变量,而不是直接使用 environ,但如果要查看整个环境,则必须使用 environ 指针。
#include <stdlib.h>
char *getenv(const char *name);
                 /* 返回值:指向与 name 关联的 value 的指针;未找到就返回 NULL */
int putenv(char *str);
                 /* 返回值:若成功,返回 0;否则,返回非 0 */
int setenv(const char *name, const char *value, int rewrite);
int unsetenv(const char *name);
                 /* 两个函数返回值:若成功,返回 0;否则,返回 -1 */

    其中:
    * getenv 是用来获取某个环境变量的值。
    * putenv 取形式为“name=value”的字符串,将其放到环境表中。如果 name 已经存在,则先删除其原来的定义。
    * setenv 将 name 设置为 value。如果 name 已经存在,则根据参数 rewrite 的值为 0与否来决定是否覆盖原来的定义。
    * unsetenv 删除 name 的定义,即使不存在也不算出错。
    注意,putenv 和 setenv 的差别在于:putenv 可以自由地将传递给它的参数字符串直接放到环境中(但不应该将存放在栈中的字符串传给它);setenv 必须分配存储空间,以便依据其参数创建 name=value 字符串。
    了解这些函数是如何修改环境表也是非常有益的。其中,环境表和环境字符串通常存放在进程存储空间的顶部(栈之上)。删除一个字符串时只需要在环境表中找到该指针,然后将所有后续指针都向环境表首部顺次移动一个位置。但是增加一个字符串或修改一个现有的字符串就困难得多。因为环境表和环境字符串通常占用的是进程地址空间的顶部,所以它不能再向高地址方向扩展,同时也不能移动在它之下的各栈帧。两者结合使得该空间的长度不能再增加。
    (1)当修改一个现有的 name 时:
    a. 如果新 value 的长度不大于现有的长度,则只要复制新字符串到原字符串所在的空间即可。
    b. 如果新 value 的长度大于原长度,则必须调用 malloc 为新字符串分配空间,然后将新字符串复制到该空间,接着使环境表中的针对 name 的指针指向新分配区。
    (2)当增加一个新的 name 时就复杂多了。必须先调用 malloc 为 name=value 字符串分配空间,然后将该字符串复制到此空间中。
    a. 如果这是第一次增加一个新的 name,则必须调用 malloc 为新的指针表分配空间。接着,将原来的环境表复制到新分配区,并将指向新 name=value 字符串的指针存放在该指针表的表尾,然后又将一个空指针存放在其后。最后使 environ 指向新指针表。如果原来的环境表位于栈顶之上,那么必须将此表移至堆中。但是此表中的大多数指针仍指向栈顶之上的各 name=value 字符串。
    b. 如果这不是第一次增加一个新的 name,则说明之前已在堆中为环境表分配了空间,所以只要调用 relloc,以分配比原空间多存放一个指针的空间,然后将指向新 name=value 的字符串的指针存放在该表表尾,后面跟着一个空指针。
  • 大小: 7.7 KB
  • 大小: 9 KB
分享到:
评论

相关推荐

    Linux系统纯C语言开发网络游戏存储引擎

    资源名称:Linux系统纯C语言开发网络游戏存储引擎 教程内容:[第1节] 1-1-1为公司搭建Linux下的c开发环境[第2节] 1-1-2为公司搭建Linux下的c开发环境[第3节] 2-1-1C语言数据类型[第4节] 2-1-2数据的快速引用[第5节]...

    C环境下DSP程序存储空间访问技术.pdf

    C环境下DSP程序存储空间访问技术.pdf

    H3C CAS 零存储环境搭建配置手册.pdf

    H3C CAS 零存储环境搭建配置手册.pdf

    ARM的C语言运行环境初始化研究

    摘要:介绍了在ADS1.2集成开发环境下,用户使用C语言编写ARM程序时,C程序的运行环境初试化,着重描述了程序中全局变量的初始化问题,对变量的存储空间分配进行了较详细的说明。

    实验二-1 keilC51编译环境的使用(C版)

    实验二-1 keilC51编译环境的使用(C版) 1. 16个数据:-8、-7、-6、-5、 -4、-3、-2、-1、0、1、2、3、4、5、6、7。将-8到1的16个数放入30H开始的RAM区,其中正数、负数分别送40H和50H开始的存储单元,正数、负数和零...

    数据结构--线性表的顺序存储结构(c语言实现)

    c语言实现的线性表顺序存储结构,包括初始化,设置线性表的值,增,删,改,查。

    C语言线性表结构实验

    (2)掌握线性表的顺序存储结构的定义及C语言实现。 (3)掌握线性表在顺序存储结构即顺序表中的各种基本操作。 2.问题描述: 假设两线性表LA和LB分别表示两集合A和B,要求新集合A=AB。 3. 数据输入: 由文件...

    谭浩强C语言word版

    3.5.4 字符数据在内存中的存储形式及使用方法 10 3.5.5 字符串常量 11 3.5.6 符号常量 12 3.6 变量赋初值 12 3.7 各类数值型数据之间的混合运算 13 3.8 算术运算符和算术表达式 14 3.8.1 C运算符简介 14 3.8.2 算术...

    C语言从入门到精通必备资料

    3.5.4 字符数据在内存中的存储形式及使用方法 41 3.5.5 字符串常量 41 3.5.6 符号常量 42 3.6 变量赋初值 42 3.7 各类数值型数据之间的混合运算 43 3.8 算术运算符和算术表达式 44 3.8.1 C运算符简介 44 3.8.2 算术...

    C语言大纲及课件

     理解:C语言程序的结构及描述方法及C语言程序的开发过程;  了解:计算机语言、C语言的发展与特点。  ⑶ 基本数据类型和表达式  掌握:整型、实型、字符型等基本数据类型及其说明方法;常量和变量的概念及其...

    C语言重点知识总结梳理

    纯手撕,如有问题欢迎指正: 思维导图解析: 从C语言初阶讲解到C语言进阶。 在C语言初阶: 1. 初识C语言 C语言的基本语法: 2. C语言分支与循环 3. C语言函数 ...25. C语言程序环境 26. C语言预处理

    H3C IT服务器存储基础精讲培训视频教程【共39集】.rar

    05 服务器各组件功能及特性-网卡及介质 06 服务器各组件功能及特性-固态硬盘颗粒 07 服务器各组件功能及特性-操作系统简介 08 硬件配置及管理_阵列级别 09 硬件配置及管理_内存保护技术 10 服务器网络基础 11 ...

    谭浩强 入门c语言教程

    1.13 Turbo C 2.0集成开发环境的使用 8 1.13.1 Turbo C 2.0简介和启动 8 1.13.2 Turbo C 2.0集成开发环境 8 1.13.3 File菜单 9 1.13.4 Edit菜单 10 1.13.5 Run菜单 11 1.13.6 Compile菜单 12 1.13.7 Project菜单 13 ...

    51单片机STC89C52RC开发板例程之AT24C02(EEPROM)记忆大于255的数程序源代码.rar

    2、开发环境:KEIL。 3、编程语言:C语言。 4、提供配套PDF格式51单片机STC89C52RC开发板电路原理图。 5、功能:由于AT24C02是每个存储地址只对应8个bit的存储空间,即一个存储单元所存储的数据最大为255,该例程...

    c语言课程设计宿舍管理系统

    c语言写的 运行环境:c-free 编写一个学生宿舍管理软件。 能使宿舍有:101,102,201,202四个房间,每个房间可住学生人。采用链表存储结构:学号、姓名、房间号、后续指针,按房间号有序,实现学生的入住、退房和查询,按...

    C语言存储空间布局以及static详解

    本文我将采用Linux环境测试C语言存储空间布局,以及采用VC6.0来测试static的常见用法。采用Linux环境来测试C语言存储空间布局,是因为Linux很容易利用shell命令中的size命令查看到进程存储区各段的大小。采用VC6.0来...

    Oracle数据库存储过程技术文档.doc

    4.1.2 Pro*c预编译环境 37 4.2 存储过程调试方法 38 4.2.1 SQL*PLUS环境中显示错误 38 4.2.2 插入测试表调试存储过程 38 4.2.3 DBMS_OUTPUT系统内置包 39 附录一 sql*plus工具 40 附录1.1 sql*plus启动和关闭 41 ...

    单片机C语言

     第四节 函数变量的存储方式和种类 第八章 Cx51构造数据类型  第一节 数组  第二节 指针  第三节 结构  第四节 共用体  第五节 枚举 第九章 单片机中断、定时器串行口的C语言编程  第一节 单片机...

    谭浩强C语言对应C语言课程PPT.zip

    1 使用Turbo C集成开发环境调试程序 1.1.源程序的编写、编辑与改错(领会); 1.2.集成环境下的求助Help(识记); 1.3.程序的编译与目标代码的生成(识记); 1.4.程序的调试(综合应用): 1.5.了解Turbo C...

Global site tag (gtag.js) - Google Analytics