关于动态内存管理

关于动态内存管理话题,我们讨论以下几个问题:

为什么存在动态内存管理?动态内存管理函数有哪些?常见的动态内存错误?什么是柔性数组?几个经典的笔试题?

问题一:为什么存在动态内存管理?

平时我们定义的变量、数组等都在栈上开辟空间,这里的局限性是,空间开辟大小固定,尤其数组还要指定长度,所需内存在编译时分配;但是,有时候我们需要的空间大小在程序运行时才能知道,因此我们需要动态内存开辟。

问题二:动态内存管理函数有哪些?

1.malloc和free

C语言提供的动态内存开辟函数:malloc

函数原型:void* malloc(sizt_t size)  它向内存申请一块连续可用的空间,返回指向这块空间的指针。

注意事项:

(1)开辟成功,返回一个指向开辟好空间的指针

(2)开辟失败,返回一个NULL指针,所以一定要检查函数的返回值

(3)返回值类型是一个void*的指针,所以说malloc函数并不知道开辟空间的类型,这个由使用者自己来决定。

(4)开辟参数大小如果为0,malloc行为未定义,取决于编译器。

C语言提供用来做动态内存的释放与回收函数:free

函数原型:void* free(void* ptr)

注意事项:

(1)如果参数ptr指向的空间不是动态开辟的,那么free函数的行为也是未定义的。

(2)如果参数ptr是NULL,则函数什么都不做

另外,malloc与free声明都在stdlib.h中。

2.calloc

            C语言还提供了一个动态内存分配函数:calloc

            函数原型:void*calloc(size_t num, size_t size) 它申请num个大小为size的空间,并且把空间的每个字节初始化为0.

            注意事项:

            (1)它与malloc函数区别在于:calloc函数会将内存初始化为0,参数不一样。

3.realloc

            C语言提供了一个内存调整函数:realloc

            函数原型:void*realloc(void* ptr, size_t size) 它是将ptr指向的内存大小调整为size,然后返回调整之后的起始地址。

            注意事项:

(1)如果原有的内存空间之后又足够大的空间,那么直接扩展大小,原数据保留。

(2)如果原内存空间之后没有足够大空间供我们调整,那么在堆空间上另找一个合适大小的连续空间,并且将原数据拷过去,并且返回这块新地址。

问题三:常见的动态内存错误?

1.     对NULL指针解引用

2.     对动态开辟的空间越界访问

3.     对不是动态开辟的内存使用free来释放

4.     使用free释放一块动态开辟内存的一部分

5.     对同一块内存多次释放

6.     动态开辟的内存忘记释放(导致内存泄漏)

问题四:什么是柔性数组?

       一个结构体中的最后一个元素允许是位置大小的数组,这个数组就叫做柔性数组。

       例如:

         1 typedef struct std

        {

          int i;

          int a[];//柔性数组,也可以写成int a[0];                                              

        }type_a;

       注意事项:

(1)结构体的柔性数组成员前面至少有一个其他成员

(2)sizeof返回的这种结构大小不包括柔性数组的内存

(3)包含柔性数组成员的结构用malloc函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

(4)可以一次为结构体分配大小(包括柔性数组),也可以将结构体育柔性数组分开动态申请,第一种方便内存释放,因为只需要释放一次,第二种方便访问(但是建议第一种)。

问题五:几个经典的笔试题?

以下4个案例运行分别会有什么样的结果,怎么改正?   

  

第一个问题:

函数没有返回值,出了函数其栈帧消失,相当于往一个空指针里面拷数据,则会导致段错误。

改法:

  6 char*  GetMemory(char* p)
  7 {
  8     p=(char*)malloc(100);
  9     return p;
 10 }
 11 
 12 void Test(void)
 13 {
 14     char* str=NULL;
 15     char* p=NULL;
 16     p=GetMemory(str);
 17     strcpy(p, "hello world\n");
 18     printf(p);
 19 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值