首先介绍一下自己的程序出错的原因,然后总结一下什么时候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. 代码重构与单元测试——使用“以查询取代临时变量”再次对Statement()方法进行重构(七)

    代码重构与单元测试(一) 代码重构与单元测试--测试项目(二) 代码重构与单元测试--"提取方法"重构(三) 代码重构与单元测试--重构1的单元测试(四) 代码重构与单元测试--对 ...

  2. Linux远程访问控制

    目录 一.SSH远程管理 1.1.定义 1.2.配置OpenSSH服务端 二.sshd服务支持两种验证方式 2.1.密码验证 2.2.使用SSH客户端程序 ssh远程登录 scp远程复制 sftp安全 ...

  3. windows中抓取hash小结(下)

    书接上回,windows中抓取hash小结(上) 指路链接 https://www.cnblogs.com/lcxblogs/p/13957899.html 继续 0x03 从ntds.dit中抓取 ...

  4. 《JERRY Hexo & GitHub 静态网站搭建说明》

    JERRY-Hexo-GitHub <JERRY Hexo & GitHub 静态网站搭建说明> 原创内容,转载请注明出处! 一.前言 1.1 什么是 Hexo? 一个基于 Nod ...

  5. 题解 P3941 入阵曲

    题解 观察数据范围,可以 \(\mathcal O(n^2m^2)\) 暴力计算,而加上特殊性质,则可以骗到 \(75pts\) 正解: 我们发现,在一维情况下,\(\mod k\) 相同的前缀和相减 ...

  6. 题解 english

    传送门 好题 肝完这题感觉头巨痛 首先\(n \leqslant 1000\)的部分可以\(n^2\)单调队列,有30pts 然后考场上魔改了下单调栈,让它能顺便维护出以\(1~i-1\)为左端点的区 ...

  7. 【AI】TorchVision_DataLoad

    From: https://liudongdong1.github.io/ All datasets are subclasses of torch.utils.data.Dataset i.e, t ...

  8. 第12篇-认识CodeletMark

    InterpreterCodelet依赖CodeletMark完成自动创建和初始化.CodeletMark继承自ResourceMark,允许自动析构,执行的主要操作就是,会按照Interpreter ...

  9. 如何使用Git建立本地仓库并上传代码到GitHub

    使用Git建立本地仓库并上传代码到GitHub 工具/原料   电脑安装git客户端.注册github账号并登陆 方法/步骤     到本地项目文件夹右键选择git bash here   输入个人信 ...

  10. 深入浅出Mybatis系列(十)---延迟加载

    一.延迟加载 resultMap可以实现高级映射(使用association.collection实现一对一及一对多映射),association.collection具备延迟加载功能. 延迟加载:先 ...