c语言中的动态内存分配

 “动态”(Dynamic)内存分配的意思是:程序运行时系统根据需要分配存储空间存储数据。注意用过后要及时释放所分配的空间,否则剩余内存空间就会越来越小,影响系统运行。

    C语言中常用malloc()和calloc()函数来动态地取得内存空间。

一、malloc()和free()函数

       malloc()和free()函数是C语言中最常用的动态内存分配与释放函数。

malloc()的格式为:指针=malloc(空间大小);

例如:ptr=malloc(100);这个指令要求计算机分配连续的100Bytes空间。malloc()函数返回该空间的首地址,且存入ptr内。

free()的格式为:free(指针);//把指针所指区域释放掉

例子:char *p;

             p=(char*)malloc(8);//开辟8个字节的存储空间,并把地址赋给指针p,通过指针p对该空间进行存取操作。

             *p='L';      //存储字符,所分配空间的第0字节存储L

              *(p+1)='o';//分配空间的第一字节存储字符'o'.

              *(p+2)='v';

              *(p+3)='e';

                *(p+4)='\0';

           puts(p);//输出字符串

         free(p);//释放空间

注意:*(p+n)等价于p[n],(p+n)是地址,而*(p+n)就是取地址(p+n)的内容。

如上面程序中的*(p+1)='A';可写成p[1]='A';

malloc()函数的参数可以是常数、变量或表达式等。除了存放字符串外,malloc()也可取得空间来存储整数等数据。例如存储整数分配空间如下:

int *ptr;

ptr=(int *)malloc(sizeof(int)*4);

malloc()开辟空间存储4个整数数据,由于malloc()总传回第0字节的地址,且返回值必定是char*类型,所以要通过(int *)来强制转换为指向整型后存入指向整型的指针ptr.

当用malloc()函数分配空间时,若计算机无法提供足够的空间分配则会返回NULL指针。所以,若返回的指针为NULL,就表示可分配的剩余空间已不足。

----------------------------------------------------------------------------------------------

 C语言动态分配系统

 C语言的内存分配

       C语言的内存分配有三种方式,即静态分配、动态分配和在栈上创建。

静态分配指在编译时在程序(进程)的数据段分配相应的空间给变量,如全局变量和静态变量,它们持续存在于进程的整个运行时,并且完全由编译器控制分配和释放。

在栈(Stack)上创建的内存也由编译器控制,用于存储函数的参数,非静态局部变量等。函数开始执行时,实参和局部变量被推入栈中;函数执行完成后,入栈的变量被推出栈。

动态分配(dynamic allocation)是程序在运行时根据实际需要从堆(Heap)上取得或交回内存的方法。所分配的内存由程序员控制,在运行时,编译器并不会自动删除它们,而是由程序员决定它们的生存期。

 

指针与动态内存分配/动态分配函数

C语言的指针为动态分配系统提供必要的支持。C的动态分配函数:

#include <stdlib.h>

void *malloc(size_t size);

void *calloc(size_t nitems, size_t size);

void *realloc(void *block, size_t size);

void free(void * block);

malloc()分配一个size大小的内存空间,并且用一个void类型的指针指向这个空间,然后返回这个指针;如果堆中内存不足,函数失败,返回空指针NULL。

       下面的代码在堆上分配1000字节,返回后,赋值给字符指针ptr;ptr指向这1000字节的首地址:

              char *ptr;

       int *iptr;

ptr = malloc (1000); /* 分配字节 */

iptr = malloc (50 * sizeof(int)); /* 为50整数分配内存 */

这里,malloc()函数的返回值在赋值给ptr和iptr时,并不需要使用强制类型转换(参《指针表达式》);但是,要注意,malloc()函数所分配的内存是未初始化的,即这块内存中的值是不确定的。

       尽管堆中的自由内存一般都很大,但它仍然是有限的,因此分配函数可能失败,返回空指针;所以,在调用分配函数后,要对它的返回值进行检查,确保指针是有效的;否则可能导致程序瘫痪。

calloc ()同样是在堆上分配内存,但它所分配的空间大小是由nitems * size决定,即分配的内存量等于nitems * size。与malloc()函数相比较,calloc ()所分配的空间会被初始化为零,即用0填充。

realloc ()用于改变已经分配的内存空间的大小。本函数在C89C99之间,存在一些不同。在C89中,realloc ()函数将先前分配的,由block指向的内存的大小改变为size的大小。size的值可以大于原来的值,也可以小于原来的值。在重新分配时,旧块(最大为size字节)中的内容被复制到新块中。在C99中,block是空闲的,并被分配了新块;新块包含着与旧块(最大size)相同的内容。函数返回指向新块的指针,新块可以与旧块的地址一样,因此,这时返回的指针可以与传入的指针一致。如果block是空指针,那么,realloc ()函数仅仅分配size字节的内存,并返回;如果size为零,那么,realloc ()函数就释放block所指向的内存。

free ()用来释放由动态分配函数分配的空间,其参数就是指向某空间的指针。注意,block必须是先前用动态分配函数(上述三个函数分配)所分配而取得的。如果传入无效指针,free ()函数可能摧毁内存管理机制,使得系统瘫痪。如果block为NULL,free ()函数不操作。

 

动态分配的数组(dynamically-allocated array)

       注意区分,动态分配的数组和动态数组(dynamic array/growable array/ resizable array/dynamic table/array list);后者如C++语言的std::vector。

       ⑴、动态分配的一维数组

1   /* 动态分配的一维数组*/

2   #include <stdlib.h>

3   #include <stdio.h>

4   #include <string.h>

5

6   int main()

7   {

8      char *s;

9      register int t;

10

11     s = malloc (80); /* 分配*/

12     if (!s) { /* 检查指针 */

13         printf ("内存分配失败");

14         exit (1);

15     }

16

17     get (s);

18     for (t=strlen (s)-1; t >= 0; putchar (s[t])); /* 反向打印 */

19

20     free (s);     /* 释放 */

21     return 0;

22  }

 

       ⑵、动态分配的二维数组

1   /* 动态分配的二维数组*/

2   /* 一个表,计算~的~次幂*/

3   #include <stdlib.h>

4   #include <stdio.h>

5

6   int pwr (int, int);

7

8   int main ()

9   {

10     /* 元素个数为的整数数组的指针*/

11     int (*iPtr)[10]; /* 这里的圆括号是必须*/

12     register int i, j;

13

14     iPtr = malloc (40 * sizeof(int)); /* sizeof确保可移植性*/

15     if (!iPtr) { /* 检查指针*/

16         printf ("内存分配失败");

17         exit (1);

18     }

19

20     for (j=1; j<11; j++)

21         for (i=1; i<5; i++) iPtr[i-1][j-1] = pwr (j, i);

22

23     for (j=1; j<11; j++) {

24         for (i=1; i<5; i++) printf ("%10d", iPtr[i-1][j-1]);

25         printf ("\n");

26     }

27

28     free (iPtr);      /* 释放*/

29     return 0;

30  }

31

32  pwr (int a, int b)

33  {

34      register int t = 1;

35

36     for (; b; b--) t = t * a;

37

38     return t;

39  }

 

动态内存分配的常见错误

常见的动态分配内存的错误有:

⑴、内存分配函数返回的是空指针,没有检查就使用其返回的指针。应该在动态分配函数返回的同时对其返回值进行检查,以防止误用。

⑵、malloc ()函数返回的内存尚未初始化就引用它。

⑶、对所分配的内存进行的操作越过了边界。如数组操作时的下标“多1”或者“少1”。

⑷、忘记了在退出程序块时调用free()函数来释放内存,造成内存泄露。动态内分配存的申请与释放必须配对,程序中malloc与free的使用次数一定要相同。

⑸、使用free()释放了内存后,没有将相应的指针设置为NULL,导致产生“野指针”(dangling pointer)。

⑹、调用free()函数释放了内存,却继续使用它。

⑺、调用free()函数释放了内存,后面再一次调用free()函数释放它。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值