[英]How can I use this unallocated memory?
為什么我使用以下程序沒有任何錯誤?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
char *pStr = (char*) malloc(25);
free(pStr);
strcpy(pStr, "foo");
printf("%s\n", pStr);
return 0;
}
不應該free(pStr)
阻止我寫信到那個地址嗎? 在使用它之前,我不必再分配空間嗎?
只要事物在語法上是正確的, free
就不會阻止你做任何事情。 因此,如果您從未在第一時間分配內存,那么您仍然非常歡迎復制到char*
。 但這是未定義的行為,並且有責任(閱讀:可能)導致程序崩潰或在沒有警告的情況下做錯事。
例如,如果您的編譯器進行了一些優化,它可能會重新排序某些指令以節省時間。 由於您釋放了內存,編譯器可能會認為在該位置為以后創建的其他數據分配內存是安全的。 如果優化器在此處移動該分配並在strcpy
之前寫入,則可以覆蓋存儲在那里的對象。
考慮以下代碼:
int main(int arc, char *argv[]){
char* pStr = (char*) malloc(25);
free(pStr);
strcpy(pStr, "foo");
printf("%s\n", pStr);
int* a = (int*) malloc(sizeof(int));
*a = 36;
printf("%d\n", *a);
}
既然你寫信給未分配的內存,你可以不知道什么任的printf
旨意顯示。 36可能已經覆蓋了一些“foo”字符串。 “foo”字符串可能覆蓋a
指向的值36。 或者也許它們都沒有影響到另一個,你的程序運行似乎很好,直到你改變一些變量的名稱並重新編譯,並且由於某種原因,即使你沒有改變任何東西,一切都搞砸了。
故事的道德:你是正確的,你不應該寫free
記憶; 但是,你不能寫入free
存儲器是不正確的。 C不會檢查這種情況,並假設您正在嘗試做一些奇特的事情。 如果您確切知道編譯器優化的方式以及在調用malloc
時分配內存的位置,您可能知道在特定情況下寫入未分配的內存是安全的,而C不會阻止您這樣做。 但是對於99.999%的時間你不了解一切 ,就是不要這樣做。
由於其他答案指出它是未定義的行為 ,因此編譯器沒有義務進行任何診斷。 但是,如果你有現代版本的gcc
( > = 4.8 )或clang
,那么在這個“免費使用后”錯誤的情況下, AddressSanitizer
可能會有所幫助:
$ gcc -ansi -pedantic -fsanitize=address check.c
$ ./a.out
=================================================================
==2193== ERROR: AddressSanitizer: heap-use-after-free on address 0x60060000efe0 at pc 0x4009a8 bp 0x7fff62e22bc0 sp 0x7fff62e22bb8
...
常見的防御性編程“技巧”是在free()
調用之后立即分配NULL
:
free(pStr), pStr = NULL;
有了它可能會在GNU / Linux上使用pStr
取消引用獲得"Segmentation fault"
,但不能保證這一點。
了解您需要了解內存分配過程的問題的答案。 在一般意義上,malloc / free是庫函數。 它們管理從操作系統服務分配的內存池。
[存在過度簡化的風險]
你的第一個malloc找到一個空池。 然后,它調用操作系統系統服務將頁面添加到要添加到池中的進程。 然后,Malloc從該池返回一塊內存。
調用free將塊返回池中。 它仍然是池中的有效內存塊。
如果您訪問freed地址,內存仍然存在。 但是,你是$ $ @ $ up up malloc的內存池。 這種訪問最終會在#$#$中輸入。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.