C语言的内存分配

上传人:ji****72 文档编号:37539548 上传时间:2018-04-18 格式:DOCX 页数:17 大小:96.92KB
返回 下载 相关 举报
C语言的内存分配_第1页
第1页 / 共17页
C语言的内存分配_第2页
第2页 / 共17页
C语言的内存分配_第3页
第3页 / 共17页
C语言的内存分配_第4页
第4页 / 共17页
C语言的内存分配_第5页
第5页 / 共17页
点击查看更多>>
资源描述

《C语言的内存分配》由会员分享,可在线阅读,更多相关《C语言的内存分配(17页珍藏版)》请在金锄头文库上搜索。

1、在任何程序设计环境及语言中,内存管理都十分重要。在目前的计算机系统或嵌入式系统中,内存资源仍然是有限的。因此在程序设计中,有效地管理内存资源是程序员首先考虑的问题。第 1 节主要介绍内存管理基本概念,重点介绍 C 程序中内存的分配,以及 C 语言编译后的可执行程序的存储结构和运行结构,同时还介绍了堆空间和栈空间的用途及区别。第 2 节主要介绍 C 语言中内存分配及释放函数、函数的功能,以及如何调用这些函数申请/释放内存空间及其注意事项。3.1 内存管理基本概念内存管理基本概念3.1.1 C 程序内存分配程序内存分配1C 程序结构程序结构下面列出 C 语言可执行程序的基本情况(Linux 2.6

2、 环境/GCC4.0)。rootlocalhost Ctest# ls test -l /test 为一个可执行程序-rwxr-xr-x 1 root root 4868 Mar 26 08:10 testrootlocalhost Ctest# file test /此文件基本情况test: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not strippedrootlocalhost Ctest# s

3、ize test /此二进制可执行文件结构情况/代码区静态数据/全局初始化数据区 未初始化数据区 十进制总和 十六进制总和 文件名text data bss dec hex filename906 284 4 1194 4aa test可以看出,此可执行程序在存储时(没有调入到内存)分为代码区(text)、数据区(data)和未初始化数据区(bss)3 个部分。(1)代码区(text segment)。存放 CPU 执行的机器指令(machine instructions)。通常,代码区是可共享的(即另外的执行程序可以调用它),因为对于频繁被执行的程序,只需要在内存中有一份代码即可。代码区通常

4、是只读的,使其只读的原因是防止程序意外地修改了它的指令。另外,代码区还规划了局部变量的相关信息。(2)全局初始化数据区/静态数据区(initialized data segment/data segment)。该区包含了在程序中明确被初始化的全局变量、静态变量(包括全局静态变量和局部静态变量)和常量数据(如字符串常量)。例如,一个不在任何函数内的声明(全局数据):int maxcount = 99;使得变量 maxcount 根据其初始值被存储到初始化数据区中。static mincount=100;这声明了一个静态数据,如果是在任何函数体外声明,则表示其为一个全局静态变量,如果在函数体内(局

5、部),则表示其为一个局部静态变量。另外,如果在函数名前加上 static,则表示此函数只能在当前文件中被调用。(3)未初始化数据区。亦称 BSS 区(uninitialized data segment),存入的是全局未初始化变量。BSS 这个叫法是根据一个早期的汇编运算符而来,这个汇编运算符标志着一个块的开始。BSS 区的数据在程序开始执行之前被内核初始化为 0 或者空指针(NULL)。例如一个不在任何函数内的声明:long sum1000;将变量 sum 存储到未初始化数据区。图 3-1 所示为可执行代码存储时结构和运行时结构的对照图。一个正在运行着的 C 编译程序占用的内存分为代码区、初

6、始化数据区、未初始化数据区、堆区和栈区 5 个部分。(点击查看大图)图 3-1 C 程序的内存布局(1)代码区(text segment)。代码区指令根据程序设计流程依次执行,对于顺序指令,则只会执行一次(每个进程),如果反复,则需要使用跳转指令,如果进行递归,则需要借助栈来实现。代码区的指令中包括操作码和要操作的对象(或对象地址引用)。如果是立即数(即具体的数值,如 5),将直接包含在代码中;如果是局部数据,将在栈区分配空间,然后引用该数据地址;如果是 BSS 区和数据区,在代码中同样将引用该数据地址。(2)全局初始化数据区/静态数据区(Data Segment)。只初始化一次。(3)未初始

7、化数据区(BSS)。在运行时改变其值。(4)栈区(stack)。由编译器自动分配释放,存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈。每当一个函数被调用,该函数返回地址和一些关于调用的信息,比如某些寄存器的内容,被存储到栈区。然后这个被调用的函数再为它的自动变量和临时变量在栈区上分配空间,这就是 C 实现函数递归调用的方法。每执行一次递归函数调用,一个新的栈框架就会被使用,这样这个新实例栈里的变量就不会和该函数的另一个实例栈里面的变量混淆。(5)堆区(heap)。用于动态内存分配。堆在内存中位于 bss 区和栈区之间。一般由程序员分配和释放,若程序员不释放,程序结束时有可能由

8、 OS 回收。之所以分成这么多个区域,主要基于以下考虑:一个进程在运行过程中,代码是根据流程依次执行的,只需要访问一次,当然跳转和递归有可能使代码执行多次,而数据一般都需要访问多次,因此单独开辟空间以方便访问和节约空间。临时数据及需要再次使用的代码在运行时放入栈区中,生命周期短。全局数据和静态数据有可能在整个程序执行过程中都需要访问,因此单独存储管理。堆区由用户自由分配,以便管理。下面通过一段简单的代码来查看 C 程序执行时的内存分配情况。相关数据在运行时的位置如注释所述。/main.cpp int a = 0; /a 在全局已初始化数据区 char *p1; /p1 在 BSS 区(未初始化

9、全局变量) main() int b; /b 在栈区char s = “abc“; /s 为数组变量,存储在栈区,/“abc“为字符串常量,存储在已初始化数据区char *p1,p2; /p1、p2 在栈区char *p3 = “123456“; /1234560 在已初始化数据区,p3 在栈区 static int c =0; /C 为全局(静态)数据,存在于已初始化数据区/另外,静态数据会自动初始化p1 = (char *)malloc(10);/分配得来的 10 个字节的区域在堆区p2 = (char *)malloc(20);/分配得来的 20 个字节的区域在堆区free(p1);fr

10、ee(p2); 2内存分配方式内存分配方式在 C 语言中,对象可以使用静态或动态的方式分配内存空间。静态分配:编译器在处理程序源代码时分配。动态分配:程序在执行时调用 malloc 库函数申请分配。静态内存分配是在程序执行之前进行的因而效率比较高,而动态内存分配则可以灵活的处理未知数目的。静态与动态内存分配的主要区别如下:静态对象是有名字的变量,可以直接对其进行操作;动态对象是没有名字的变量,需要通过指针间接地对它进行操作。静态对象的分配与释放由编译器自动处理;动态对象的分配与释放必须由程序员显式地管理,它通过 malloc()和 free两个函数(C+中为 new 和 delete 运算符)

11、来完成。以下是采用静态分配方式的例子。int a=100;此行代码指示编译器分配足够的存储区以存放一个整型值,该存储区与名字 a 相关联,并用数值 100 初始化该存储区。以下是采用动态分配方式的例子。p1 = (char *)malloc(10*sizeof(int);/分配得来得 10*4 字节的区域在堆区此行代码分配了 10 个 int 类型的对象,然后返回对象在内存中的地址,接着这个地址被用来初始化指针对象 p1,对于动态分配的内存唯一的访问方式是通过指针间接地访问,其释放方法为:free(p1);3.1.2 栈和堆的区别栈和堆的区别前面已经介绍过,栈是由编译器在需要时分配的,不需要时

12、自动清除的变量存储区。里面的变量通常是局部变量、函数参数等。堆是由 malloc()函数(C+语言为 new 运算符)分配的内存块,内存释放由程序员手动控制,在 C 语言为free 函数完成(C+中为 delete)。栈和堆的主要区别有以下几点:(1)管理方式不同。)管理方式不同。栈编译器自动管理,无需程序员手工控制;而堆空间的申请释放工作由程序员控制,容易产生内存泄漏。(2)空间大小不同。)空间大小不同。栈是向低地址扩展的数据结构,是一块连续的内存区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,当申请的空间超过栈的剩余空间时,将提示溢出。因此,用户能从栈获得的空间较小。堆是向

13、高地址扩展的数据结构,是不连续的内存区域。因为系统是用链表来存储空闲内存地址的,且链表的遍历方向是由低地址向高地址。由此可见,堆获得的空间较灵活,也较大。栈中元素都是一一对应的,不会存在一个内存块从栈中间弹出的情况。(3)是否产生碎片。)是否产生碎片。对于堆来讲,频繁的 malloc/free(new/delete)势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低(虽然程序在退出后操作系统会对内存进行回收管理)。对于栈来讲,则不会存在这个问题。(4)增长方向不同。)增长方向不同。堆的增长方向是向上的,即向着内存地址增加的方向;栈的增长方向是向下的,即向着内存地址减小的方向。(5)

14、分配方式不同。)分配方式不同。堆都是程序中由 malloc()函数动态申请分配并由 free()函数释放的;栈的分配和释放是由编译器完成的,栈的动态分配由 alloca()函数完成,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行申请和释放的,无需手工实现。(6)分配效率不同。)分配效率不同。栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行。堆则是 C 函数库提供的,它的机制很复杂,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大的空间,如果没有足够大的空间(可

15、能是由于内存碎片太多),就有需要操作系统来重新整理内存空间,这样就有机会分到足够大小的内存,然后返回。显然,堆的效率比栈要低得多。3.1.3 Linux 数据类型大小数据类型大小在 Linux 操作系统下使用 GCC 进行编程,目前一般的处理器为 32 位字宽,下面是/usr/include/limit.h 文件对 Linux 下数据类型的限制及存储字节大小的说明。/* We dont have #include_next. Define ANSI for standard 32-bit words. */* These assume 8-bit chars, 16-bit short int

16、s, and 32-bit ints and long ints. */1char 数据类型数据类型char 类型数据所占内存空间为 8 位。其中有符号字符型变量取值范围为?128127,无符号型字符变量取值范围为0255。其限制如下:/* Number of bits in a char. */# define CHAR_BIT 8 /所占字节数/* Minimum and maximum values a signed char can hold. */ /有符号字符型范围# define SCHAR_MIN (-128)# define SCHAR_MAX 127/* Maximum value an unsigned char can hold. (Minimum is 0.) */

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号