首先介绍一下自己的程序出错的原因,然后总结一下什么时候free会失败。

1.程序伪代码

// 已知payload已经指向一部分内存数据
char * payload;
int payload_len; //payload的长度 char * front_pkt="xxxxxxxxx"; // 申请内存
char * temp_ptr=(char *); malloc(payload_len+strlen(front_pkt)+1);// 多申请一位放\0
memset(temp_ptr,0,payload_len+strlen(front_pkt)+1); // 拷贝
strcat(temp_ptr,front_pkt);
strcat(temp_ptr,payload); // 错误原因就发生在这里
... // 释放
free(temp_ptr);//报错的地方

定位过程:

由于是和别的程序联调,首先定位出事free()函数时报的错。然后就开始从为指针申请内存的地方开始定位,最后发现,在strcat(temp_ptr,payload)之后,指针temp_ptr指向的数据竟然比我申请的内存要大,尾部有一部分杂数据。至此,发现是内存越界了。

为什么会越界呢?因为payload并不能保证是字符串,即不能保证是符号'\0'结尾的。在使用strcat追加拷贝字符串时是根据'\0'符号来判断拷贝结束的。所以非常有可能发生内存越界的行为。

修改方案:使用strncat()函数,指定拷贝的长度。

定位心得:

1.在使用C语言的字符串函数时,str开头的,一定要确保指针指向的内存是字符串,即'\0'结尾。

2.尽量使用带n的函数,指定内存、字符串拷贝等的长度,可以避免不必要的麻烦。

总结:什么时候free(p)会报错?

1.如果p不是NULL指针,对p连续操作两次就导致程序运行错误

2.内存越界,指针初始值被修改掉,和别的区块内存重叠,分配的这段内存的“门牌号”被改掉了,free就会失败。比如上边的例子。

引申:free的原理

free(p)释放p指向的内存时,并不需要提供要释放内存的大小,这是因为在p附近的某个位置存放有维护该内存区域的数据,这是由内存申请函数malloc等产生的。实际上在p之前有个结构体,记录了该块内存的信息。如果程序因为内存越界修改了结构体,则会导致free()函数报错返回,并不释放任何内存。

以上边的例子,strcat(temp_ptr,payload),向申请的内存中拷贝了过多的数据。

注:由于知识有限,本文所讲必定有缺陷之处,请谨慎参考,如有错误之处,请批评指正!

记录一次C语言中free(p)失败的更多相关文章

  1. Java 语言中 Enum 类型的使用介绍

    Enum 类型的介绍 枚举类型(Enumerated Type) 很早就出现在编程语言中,它被用来将一组类似的值包含到一种类型当中.而这种枚举类型的名称则会被定义成独一无二的类型描述符,在这一点上和常 ...

  2. ZH奶酪:C语言中malloc()和free()函数解析

    1.malloc()和free()的基本介绍 (1)函数原型及说明 void *malloc(long NumBytes) 该函数分配了NumBytes个字节,并返回了指向这块内存的指针.如果分配失败 ...

  3. C语言中setjmp与longjmp学习笔记

    C语言中setjmp与longjmp学习笔记 一.基础介绍 头文件:#include<setjmp.h> 原型:  int setjmp(jmp_buf envbuf) ,然而longjm ...

  4. C语言中 malloc函数用法

    一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针 ...

  5. Java语言中:float、double数据类型在内存中是如何存储的

    引用参考 https://www.cnblogs.com/chenmingjun/p/8415464.html#4291528 https://blog.csdn.net/yansmile1/arti ...

  6. c语言中的malloc函数

    少壮不努力,大一的时候c语言学得不扎实,最近学数据结构的时候看到c语言中malloc函数都不知道了,这里记录一下,避免以后再忘. malloc的全称是memory allocation,中文叫动态内存 ...

  7. C语言中 malloc

    参考:https://blog.csdn.net/kokodudu/article/details/11760863 一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: ...

  8. C语言中,头文件和源文件的关系(转)

    简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程: 1.预处理阶段 2.词法与语法分析阶段 3.编译阶段,首先编译成纯汇编语句, ...

  9. C 语言中 setjmp 和 longjmp

    在 C 语言中,我们不能使用 goto 语句来跳转到另一个函数中的某个 label 处:但提供了两个函数——setjmp 和 longjmp来完成这种类型的分支跳转.后面我们会看到这两个函数在处理异常 ...

随机推荐

  1. 1065 A+B and C (64bit) (20分) 测试点3 别用cin

    cin的话,处理不了这么大的数?? 要拐回scanf("%lld"): 啊啦搜

  2. 徒手打造基于Spark的数据工厂(Data Factory):从设计到实现

    在大数据处理和人工智能时代,数据工厂(Data Factory)无疑是一个非常重要的大数据处理平台.市面上也有成熟的相关产品,比如Azure Data Factory,不仅功能强大,而且依托微软的云计 ...

  3. SpringBoot Spring Security 核心组件 认证流程 用户权限信息获取详细讲解

    前言 Spring Security 是一个安全框架, 可以简单地认为 Spring Security 是放在用户和 Spring 应用之间的一个安全屏障, 每一个 web 请求都先要经过 Sprin ...

  4. 物联网协议Coap协议介绍

    COAP协议简介 Coap(Constrained Application Protocol)是一种在物联网世界的类web协议,它的详细规范定义在 RFC 7252.COAP名字翻译来就是" ...

  5. vs2019 快捷键汇总

    https://docs.microsoft.com/zh-cn/visualstudio/ide/default-keyboard-shortcuts-for-frequently-used-com ...

  6. 【java web】拦截器inteceptor

    一.简介 java里的拦截器提供的是非系统级别的拦截,也就是说,就覆盖面来说,拦截器不如过滤器强大,但是更有针对性. Java中的拦截器是基于Java反射机制实现的,更准确的划分,应该是基于JDK实现 ...

  7. ARP:地址解析协议

    我们假设这样一个场景:你需要和你网络中的一个设备进行通信,这个设备可能是某种服务器.你用来创建这个通信的应用已经得到了这个远程主机的ip地址,也意味着系统已经有了用来构建它想要在第三层到第7层传递数据 ...

  8. 【GIS】点图层符号的方向和大小

    方向:根据属性字段设置点图层中每个要素的符号方向和大小, 1 所有要素使用同一种符号---简单渲染 在图层属性---符号系统---单一符号中进行设置,首先设置符号,在后面的[高级]选项按钮中分别设置[ ...

  9. (5)air202读取串口数据并上传到阿里云显示

    一.首先进行云端设置 根据串口助手显示的信息,以及模块文档说明我们可以知道 其中red和ir是红光LED的原始数据, HR表示心率值, HRvalid是心率是否有效标识, SP02是血氧数值,,SPO ...

  10. VS code快速创建vue模板

    忘记了.vue文件的格式或者不想手动敲那段模板代码怎么办?VS code快速创建vue模板帮你偷个小懒 第一步:新建模板并保存 打开 VS code,依次点击 file > Preference ...