当前位置: 首页 > news >正文

C语言:动态内存分配(3)

常见的动态内存错误:

1、对NULL指针的解引用操作

void test()
{
    int*p=(int*)malloc(INT_MAX/4);
    *p= 20;//如果p的值是NULL,就会有问题
    free(p);
}

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

void test()
{
    int i=0;
    int*p=(int*)malloc(10*sizeof(int));
    if(NULL== p)
    {
       exit(EXIT_FAILURE);
    }
    for(i=0;i<=10;i++)
    {
       *(p+i)=i;//当i是10的时候越界访问
    }
    free(p);
}

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

void test()
{
    int a=10;
    int *p=&a;
    free(p);//定义的a是栈区的,不能用free释放
}

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

void test()
{
    int*p=(int*)mal1oc(100);
    p++;
    free(p);//p不再指向动态内存的起始位置
}

5、对同一块动态内存多次释放

void test()
{
    int *p= (int*)malloc(100);
    free(p);
    free(p);//重复释放
}

6、动态开辟内存忘记释放(内存泄露)

while(1)
{
   malloc(1);//内存不释放,占的内存会越来越大
}

所以切记:动态开辟的空间一定要释放,并且正确释放

下面有四道关于动态内存分配错误的笔试题:
第一题:

void GetMemory(char*p)
{
     p=(char*)malloc(100);
}
void Test(void)
{
     char*str=NULL;
     GetMemory(str);
     strcpy(str, "hello world') ;
     printf(str);
}
int main()
{
     test () ;
}

答:该程序是错误的。因为test运行之后,p申请的内存空间其实并没有给到str,因此str无法打印出hello world。而且p申请的内存并没有进行free操作,造成了内存泄漏。

第二题:

char*GetMemory(void)
{
      char p[]="hello world";
      return p;
}
void Test(void)
{
      char*str=NULL;
      str=GetMemory;
      printf(str);
}
int main()
{
      test();
      return 0;
}

答:该程序是有问题的。该题虽然return p了,但是在GetMemory函数结束之后,p销毁了。因此p成为了野指针。

第三题:

void GetMemory(char**p,int num)
{
      *p=(char*)malloc(num);
}
void test(void)
{
      char*str=NULL;
      GetMemory(&str,100);
      strcpy(str,"hello");
      printf(str);
}
int main()
{
      test();
      return 0;
}

答:该程序存在内存泄漏问题,没有free释放。但是该题可以正常打印出hello,因为vp接收的是str的地址,因此p申请到内存空间时,str就是其首地址。因此可以打印出。

第四题:

void*Test(void)
{
    char*str=(char*)malloc(100);
    strcpy(str,"hello");
    free(str);
    if(str!=NULL);
    {
           strcpy(str,"world");
           printf("str");
    }
}

int main()
{
    Test();
    return 0;
}

答:该程序free提前释放了,释放完后再将world字符拷贝进去,可是那块空间已经不属于str了,造成了非法访问。结构虽然能打印出world,但是还是有问题存在的。

相关文章:

  • 基于纳芯微产品的尾灯方案介绍
  • 设置程序以管理员权限运行无效问题的排查过程分享
  • MySQL密码不要用0开头!!!
  • Java项目:ssm高校党员管理系统
  • RabbitMQ--延迟队列--使用/原理
  • Linux基础 - Web服务基础
  • 高新技术企业认定八大条件、八大领域、四项指标
  • 异常练习题(Java)
  • 那些惊艳一时的 CSS 属性
  • ipv6地址概述——深入讲解ipv6地址
  • 这才是Git的正确学习方式
  • Linux 命令(204)—— ss 命令
  • 第十四届蓝桥杯模拟赛 第二期题解
  • [激光原理与应用-29]:典型激光器 -1- 固体激光器
  • Redis常见问题
  • 07.Android之多媒体问题
  • 2017 年终总结 —— 在路上
  • Android Studio:GIT提交项目到远程仓库
  • canvas 绘制双线技巧
  • conda常用的命令
  • Cookie 在前端中的实践
  • JavaScript 基础知识 - 入门篇(一)
  • Linux快速复制或删除大量小文件
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • Terraform入门 - 1. 安装Terraform
  • Webpack 4 学习01(基础配置)
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 盘点那些不知名却常用的 Git 操作
  • 前端工程化(Gulp、Webpack)-webpack
  • 深度学习在携程攻略社区的应用
  • 详解NodeJs流之一
  • 小试R空间处理新库sf
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • 整理一些计算机基础知识!
  • ​ssh免密码登录设置及问题总结
  • ​决定德拉瓦州地区版图的关键历史事件
  • #Linux(make工具和makefile文件以及makefile语法)
  • #Linux(帮助手册)
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (第一天)包装对象、作用域、创建对象
  • (附源码)计算机毕业设计大学生兼职系统
  • (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • (转)http-server应用
  • *上位机的定义
  • .mysql secret在哪_MySQL如何使用索引
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .NET/C# 项目如何优雅地设置条件编译符号?
  • .net反编译工具
  • .net反混淆脱壳工具de4dot的使用
  • .NET性能优化(文摘)
  • .net中调用windows performance记录性能信息