記錄一次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),向申請的內存中拷貝了過多的數據。

 

注:由於知識有限,本文所講必定有缺陷之處,請謹慎參考,如有錯誤,歡迎批評指正!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM