C 存储及环境ITeye - 亚美娱乐

C 存储及环境ITeye

2019年03月27日08时24分55秒 | 作者: 星泽 | 标签: 环境,指针,字符串 | 浏览: 153

  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 的字符串的指针寄存在该表表尾,后边跟着一个空指针。
版权声明
本文来源于网络,版权归原作者所有,其内容与观点不代表亚美娱乐立场。转载文章仅为传播更有价值的信息,如采编人员采编有误或者版权原因,请与我们联系,我们核实后立即修改或删除。

猜您喜欢的文章

阅读排行

  • 1

    Linux top 指令ITeye

    进程,信息,百分比
  • 2

    C 存储及环境ITeye

    环境,指针,字符串
  • 3
  • 4

    jvm部分指令ITeye

    检查,参数,显现
  • 5

    Bat根底ITeye

    运用,树立,子目录
  • 6
  • 7

    SSH原理与运用ITeye

    运用,登录,长途
  • 8

    service指令ITeye

    指令,效劳,封闭
  • 9

    Linux指令协助ITeye

    指令,协助,东西
  • 10