动态内存管理 干货2

目录

七.常见的动态内存的错误

1.对空指针进行解引用操作。

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

3.对非动态开辟的内存使用free释放

4.动态开辟内存忘记释放,造成内存泄漏!!

八.动态内存经典笔试题

1.

2.

3.

九.柔性数组


小伙伴们,看本篇文章之前,可以先去看我的博客里的"动态内存管理 干货1",再看这篇!!

七.常见的动态内存的错误

1.对空指针进行解引用操作。

上篇文章有讲到其中一个比较重要的步骤就是:要判断返回值是否是空指针。如果你没有对返回值进行是否是NULL的判断,直接进行解引用操作,编译器会怀疑这个变量是否是NULL,会报错

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

3.对非动态开辟的内存使用free释放

上篇文章有讲过,free只可以对动态开辟的空间进行空间释放!!

4.动态开辟内存忘记释放,造成内存泄漏!!

这里是将malloc申请的空间赋值给p了,但是p是局部变量,只在函数内部有效,函数执行结束后,该变量所占用的内存地址会被释放,外部没办法再找到它,访问它,使用它。那么这时候想去释放空间,都找不到,那么就代表那块空间不仅没用了,还是释放不了给其他人用,相当于白白占用着空间。

重点:

malloc,calloc,realloc在申请空间后,不想使用空间了,就用free释放

如果没有使用free释放,当程序运行结束后,也会被操作系统回收和释放的。

那么有人就会问:既然操作系统会帮我们回收并释放内存,那又何必free?

操作系统不是立即回收释放的。如果你不主动用free释放,系统不会管它们,会一直占用着内存资源。只有程序结束后,系统才会将所有的内存回收,可是这期间,程序就可能因为内存不足或内存泄漏出问题。

八.动态内存经典笔试题

1.

图1

首先,102行是传值调用。(因为它传的是str本身,而不是str的地址,比如&str)

str是空指针,Getmeory将str传给p,其实就是将NULL传给p。

然后malloc申请100个字节的空间,并将这100个字节的空间的首地址传给p。

出了函数,函数执行结束后,变量p的内存空间被释放,外部就没办法再找到,访问并使用它!

所以现在回到103行,这个str里面还是NULL,但是strcpy参数部分,必须得是有效指针,指向有效地址,而NULL指向无效地址,所以程序会崩溃!!

其次就是,malloc申请内存空间后,使用完并没有free释放,可能会造成内存泄漏!!

那么,我们可以修改一下上面的代码!!(修改过程打上序号)

图2

还有一种修改方式:(修改过程打上序号)

图3

2.

图4

  • 这个代码也是有问题的。因为p在函数执行结束后,内存空间会被释放,外部无法再访问和使用它。
  • 那有人就会有疑惑,那图3也是return p,为什么图3的代码就是正确的?
  • 因为图3中是在堆区申请内存。堆区的内存不会像栈区局部变量那样,在函数结束时会自动回收内存空间,它需要手动free释放,直到程序结束后才会自动回收并释放。但是图4中的p是局部数组变量,局部变量存储在栈区!

所以说在16行赋值之后,str里存的是字符串首元素的地址,但是有地址却访问不到它所指向的空间,因为空间已被回收,进而也就在17行打印不出来。

那么这时候,str是非法访问,并且str是野指针!!

如果是这样,返回的是一个值,这没问题。但如果返回的是地址(例如:return &n),就是错误的,因为地址的空间会被回收!

图5

3.

图6

这里的代码错误是:

60行的str里面是申请的那100个空间的首地址,61行,str里放的是hello,62行把str的空间释放了,也就是外部对str没有访问和使用权限了,但是地址依然在(hello的地址),只是空间没了。

再到下面65行,这里其实就是对str的非法访问了,world覆盖了str里原有的hello。

即:非法访问空间并篡改了内容!!

记住:空间被收回或释放的指针,极有可能成为野指针。且空间被收回或释放的指针,不可以再被外界访问并使用,因为是非法访问

九.柔性数组

1.什么是柔性数组?

  • 在结构体中
  • 是最后一个成员
  • 并且是一个数组
  • 并且该数组并未指定大小

柔性数组的特点:

  • 结构体中的柔性数组成员前面必须至少有一个其他成员
  • sizeof返回结构体大小不包含柔性数组的部分
  • 包含柔性数组成员的结构体用malloc进行动态内存分配,分配的内存应该大于结构的大小。以适应柔性数组的预期大小

当你用malloc函数去申请空间时,也可以用realloc,这样就方便将这个数组的空间变大或变小,所以叫"柔"性数组。

相关推荐
say_fall4 小时前
C语言底层学习(2.指针与数组的关系与应用)(超详细)
c语言·开发语言·学习
祐言QAQ5 小时前
(超详细,于25年更新版) VMware 虚拟机安装以及Linux系统—CentOS 7 部署教程
linux·运维·服务器·c语言·物联网·计算机网络·centos
Ziyoung5 小时前
【探究】C语言-类型转换问题
c语言
JasmineX-17 小时前
数据结构——静态链表(c语言笔记)
c语言·数据结构·链表
学不动CV了9 小时前
ARM单片机中断及中断优先级管理详解
c语言·arm开发·stm32·单片机·嵌入式硬件·51单片机
番茄大杀手9 小时前
C/C++柔性数组
c语言·柔性数组
冉佳驹10 小时前
C语言 ——— 操作符
c语言·操作符·隐式类型转换·原、反、补码·左移右移操作符·结构成员访问操作符·按位操作符
l1t10 小时前
测试duckdb的C插件模板的编译加工和加载
c语言·开发语言·数据库·插件·duckdb
hhhwx66613 小时前
Linux学习记录--利用信号量来调度共享资源(2)
linux·c语言·c++·学习