记录一次C语言中free(p)失败
首先介绍一下自己的程序出错的原因,然后总结一下什么时候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)失败的更多相关文章
- Java 语言中 Enum 类型的使用介绍
Enum 类型的介绍 枚举类型(Enumerated Type) 很早就出现在编程语言中,它被用来将一组类似的值包含到一种类型当中.而这种枚举类型的名称则会被定义成独一无二的类型描述符,在这一点上和常 ...
- ZH奶酪:C语言中malloc()和free()函数解析
1.malloc()和free()的基本介绍 (1)函数原型及说明 void *malloc(long NumBytes) 该函数分配了NumBytes个字节,并返回了指向这块内存的指针.如果分配失败 ...
- C语言中setjmp与longjmp学习笔记
C语言中setjmp与longjmp学习笔记 一.基础介绍 头文件:#include<setjmp.h> 原型: int setjmp(jmp_buf envbuf) ,然而longjm ...
- C语言中 malloc函数用法
一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针 ...
- Java语言中:float、double数据类型在内存中是如何存储的
引用参考 https://www.cnblogs.com/chenmingjun/p/8415464.html#4291528 https://blog.csdn.net/yansmile1/arti ...
- c语言中的malloc函数
少壮不努力,大一的时候c语言学得不扎实,最近学数据结构的时候看到c语言中malloc函数都不知道了,这里记录一下,避免以后再忘. malloc的全称是memory allocation,中文叫动态内存 ...
- C语言中 malloc
参考:https://blog.csdn.net/kokodudu/article/details/11760863 一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: ...
- C语言中,头文件和源文件的关系(转)
简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程: 1.预处理阶段 2.词法与语法分析阶段 3.编译阶段,首先编译成纯汇编语句, ...
- C 语言中 setjmp 和 longjmp
在 C 语言中,我们不能使用 goto 语句来跳转到另一个函数中的某个 label 处:但提供了两个函数——setjmp 和 longjmp来完成这种类型的分支跳转.后面我们会看到这两个函数在处理异常 ...
随机推荐
- Android工程师所必经的三个阶段,你到哪个阶段了?
前言 最近一直在思考,作为一名软件开发工程师,到底应该如何实现自我成长,是否有捷径而言?其实断断续续有过很多思考,也有和各种年龄段的同学们做过不少交流,结合自身的经历,有一些感悟和思考.本文可能可以适 ...
- for循环中++i和i++的区别
语法 for (语句1; 语句2; 语句3) { 被执行的代码块 } 语句 1 在循环(代码块)开始前执行 语句 2 定义运行循环(代码块)的条件 语句 3 在循环(代码块)已被执行之后执行(这就是循 ...
- zookeeper查看启动状态报错:Error contacting service. It is probably not running.
问题描述 我有三台虚拟机master.slave1.slave2.每台虚拟机启动zkServer.sh时都没有报错,然后紧接着查看zkServer.sh的状态,这时候出现了错误:Error conta ...
- 嵌入式linux启动过程详解
启动第一步--加载BIOS 当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它.这是因为BIOS中包含了CPU的相关信息.设备启动顺序信息.硬 ...
- chromium调试技巧
调试技巧: 1.多进程不方便跟踪渲染进程,单渲染进程的设置方法 command_line->AppendSwitchWithValue("--renderer-process- ...
- 0基础学小程序----day1
17的书,那时候微信小程序开发程序还是v0.01 19年都v1.02了.位置都不一样了,枯了 技术准备:WXML使用方法类似于HTML,(都不会) 自己的样式语言WXSS兼容了CSS(都不会) 使用J ...
- 计算机网络 中国大学MOOC 哈尔滨工业大学 习题答案
转自 https://blog.csdn.net/qq_37514135/article/details/82733651 计算机网络作业题 第一章 第一题 如图所示网络.A在t=0时刻开始向C发送一 ...
- 遇到的JDBC的一些简单错误
遇到的JDBC的一些简单错误 复习java swing的使用的时候,把东西都写好了,但是在进行数据库连接的时候,出现了错误 java.lang.ClassNotFoundException: com. ...
- 高效编程:在IntelliJ IDEA中使用VIM
硬核干货分享,欢迎关注[Java补习课]成长的路上,我们一起前行 ! <高可用系列文章> 已收录在专栏,欢迎关注! 概述 Vim是一个功能强大.高度可定制的文本编辑器; 具体有多强大,我现 ...
- Arduino连接L298n驱动板驱动小车的电机
1.L298N介绍 先来讲讲电机驱动,驱动一般使用L298N,L298N 是一种双H桥电机驱动芯片,其中每个H桥可以提供2A的电流,功率部分的供电电压范围是2.5-48v,逻辑部分5v供电,接受5vT ...