【落羽的落羽 C语言篇】动态内存管理·下

文章目录

  • 一、常见动态内存使用错误
      1. 对NULL空指针进行了解引用操作
      1. 对动态开辟的空间越界访问
      1. 对非动态内存开辟内存的空间使用free释放
      1. 使用free释放一块动态开辟内存的一部分
      1. 对一块内存进行多次free释放
      1. 动态开辟的内存没有free释放
  • 二、经典笔试题练习:动态内存管理
    • 练习1
    • 练习2
    • 练习3
    • 练习4

一、常见动态内存使用错误

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

c 复制代码
int* p = (int*)malloc(INT_MAX);
*p = 12;
free(p);

p的空间可能会开辟失败,p有可能是NULL空指针。众所周知,空指针是不能直接进行解引用操作的。不对p检查就直接解引用,就可能出问题。

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

c 复制代码
int* p = (int*)malloc(10*sizeof(int));
assert(p!=NULL);
for(int i=0 ; i<12 ; i++)
    *(p+i) = i;
free(p);

很好理解,开辟好的内存空间多大就是多大,再去越界访问就不礼貌了。

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

c 复制代码
int a = 6;
int* p = &a;
free(p);

上期讲过,free释放不是动态开辟的内存,结果是未知的,换句话说,是错误的。

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

c 复制代码
int* p = (int*)malloc(10);
assert(p != NULL);
p += 2;
free(p);

此时,p不再指向这块开辟空间的开头了。因为free回收的是以参数指针为起点的空间,所以p前的这两字节空间无法被free回收了。

5. 对一块内存进行多次free释放

c 复制代码
int* p = (int*)malloc(10);
assert(p != NULL);
free(p);
free(p);

重复free,无意义

6. 动态开辟的内存没有free释放

c 复制代码
int* p = (int*)malloc(10);
assert(p != NULL);
*p = 20;
......

忘记释放使用完的动态内存,会造成内存泄漏

牢记:malloc(或calloc)和free是成对出现的,动态开辟出的内存一定要释放,并且要正确释放。

二、经典笔试题练习:动态内存管理

以下的test函数都会产生什么效果?

练习1

c 复制代码
void GetMemory(char* p)
{
    p = (char*)malloc(100);
}

void test()
{
    char* str = NULL;
    GetMemory(str);
    strcpy(str, "Hello world");
    printf("%s",str);
}

解析:函数void GetMemory(char* p)传参str时,p是形式参数,是str的一份拷贝,在这个函数里面对p的申请空间不会影响str的空间。所以,离开GetMemory函数后str还是一个NULL空指针。而strcpy的完成中,其实是有一步解引用的操作的。对str解引用,就是非法访问了,程序会崩溃。

练习2

c 复制代码
char* GetMemory()
{
    char p[] = "Hello world";
    return p;
}

void test()
{
    char* str = NULL;
    str = GetMemory();
    printf("%s",str);
}

解析:函数char* GetMemory()虽然返回指针p,但p指向的空间会在退出函数的时候就被释放,返回的p变成了野指针,str也变成了野指针。打印出的结果是随机的:

练习3

c 复制代码
void GetMemory(char** p, int num)
{
    *p = (char*)malloc(num);
}

void test()
{
    char* str = NULL;
    GetMemory(&str, 100);
    strcpy(str, "Hello mihoyo");
    printf("%s", str);
}

从结果上看,这段代码是没有问题的:

唯一的问题是:使用malloc后没有free掉开辟的空间,会造成内存泄漏,在test函数的最后加一句free(str);就好了。

练习4

c 复制代码
void test()
{
    char* str = (char*)malloc(100);
    strcpy(str, "Hello mihoyo");
    free(str);
    if(str != NULL)
    {
        strcpy(str, "Hello mihoyo");
        printf("%s",str);
    }
}

解析:第一次的strcpy完成后,str指向的动态内存空间被free掉了。但str的值没有被改变,它还是指向着那一块空间,但那块空间已经不属于它了,str已经是一个野指针了。str并不是NULL空指针,所以还会进入下面的if语句中,但strcpy和printf函数的执行就是非法访问了。结果可能是对的,但是有很大的安全隐患。

本篇完,感谢阅读

相关推荐
Icomi_2 小时前
【PyTorch】7.自动微分模块:开启神经网络 “进化之门” 的魔法钥匙
c语言·c++·人工智能·pytorch·python·机器学习·计算机视觉
ElvInR2 小时前
【C语言】动态内存管理
c语言·开发语言
嘻嘻哈哈的zl4 小时前
初级数据结构:栈和队列
c语言·开发语言·数据结构
weixin_537590455 小时前
《C程序设计》第六章练习答案
c语言·c++·算法
charlie1145141916 小时前
从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(OLED设备层封装)
c语言·stm32·单片机·教程·oled·嵌入式软件
小林up7 小时前
【C语言设计模式学习笔记1】面向接口编程/简单工厂模式/多态
c语言·设计模式
涛ing11 小时前
32. C 语言 安全函数( _s 尾缀)
linux·c语言·c++·vscode·算法·安全·vim
厂太_STAB_丝针13 小时前
【自学嵌入式(8)天气时钟:天气模块开发、主函数编写】
c语言·单片机·嵌入式硬件
charlie11451419114 小时前
从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(协议层封装)
c语言·驱动开发·单片机·学习·教程·oled
*TQK*14 小时前
ZZNUOJ(C/C++)基础练习1041——1050(详解版)
c语言·c++·编程知识点