记录一次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),向申请的内存中拷贝了过多的数据。
注:由于知识有限,本文所讲必定有缺陷之处,请谨慎参考,如有错误,欢迎批评指正!
本文来自博客园,作者:一只奋斗的考拉,转载请注明原文链接:https://www.cnblogs.com/liu13526825661/p/15307532.html