[英]How much memory does calloc actually allocate?
經過測試的以下代碼將輸出顯示為
1
0
0
2
0
這是驚人的,因為ptr [3],ptr [4]沒有任何內存分配。 盡管他們在其中存儲了價值並打印出來。 我為ptr [i]中的幾個較大的i嘗試了相同的代碼,該代碼再次成功編譯並給出了結果,但是對於非常大的i值(約100000),程序崩潰了。 如果calloc()在單次調用中分配了如此大的內存,那么它就不值得有效。 那么calloc()如何工作? 這個差異在哪里?
#include <stdio.h>
void main() {
int * ptr = (int *)calloc(3,sizeof(int));//allocates memory to 3 integer
int i = 0;
*ptr = 1;
*(ptr+3) = 2;//although memory is not allocated but get initialized
for( i =0 ; i<5 ; ++i){
printf("%d\n",*ptr++);
}
}
之后,我嘗試了此代碼,該代碼可以連續運行而沒有任何輸出
#include <stdio.h>
void main() {
int * ptr = (int *)calloc(3,sizeof(int));
int i = 0;
*ptr = 1;
*(ptr+3) = 2;
//free(ptr+2);
for( ; ptr!=NULL ;)
{
//printf("%d\n",*ptr++);
i++;
}
printf("%d",i);
}
您正在混淆兩種內存分配:內核的和libc的。
當您要求malloc
或calloc
提供5個字節時,它不會掉頭並向內核請求5個字節。 那將永遠 。 相反,libc堆系統從內核獲取更大的內存塊,並將其細分。
因此,當您需要少量的內存時,通常在libc尚未分配的內存之后就有大量可訪問的內存,您可以訪問它。 當然,訪問它是漏洞的即時解決方案。
引用末尾的唯一時間將是SIGnal,這是如果您恰好位於從內核獲取的區域的最后。
我建議您嘗試在valgrind
下運行測試用例,以獲取更多信息。
您擁有的代碼具有未定義的行為。 但是,您不會崩潰,因為malloc
和calloc
實際上經常分配比您要求的更多的內存。
告訴您有多少內存的一種方法是調用增加大小的realloc
,直到您獲得的指針與原始指針不同為止。 盡管該標准不能保證該技巧會奏效,但通常會產生良好的效果。
您可以通過以下方法進行此實驗:
int *ptr = calloc(1,sizeof(int));
// Prevent expansion of the original block
int *block = calloc(1, sizeof(int));
int *tmp;
int k = 1;
do {
tmp = realloc(ptr, k*sizeof(int));
k++;
} while (tmp == ptr);
printf("%d\n", k-1);
這將在我的系統和ideone上打印4
( ideone上的演示 )。 這意味着當我請求4個字節(即calloc
一個sizeof(int)
時,我有足夠的空間可容納16個字節(即4 * sizeof(int) ). This does not mean that I can freely write up to four
int s after requesting memory for a single
但是, s after requesting memory for a single
int` s after requesting memory for a single
:超出請求的內存邊界寫入仍然是未定義的行為。
calloc
在給定代碼段中為3
int
分配內存。 實際上,您正在訪問未分配的內存。 訪問未分配的內存會調用未定義的行為 。
calloc僅分配您要求的內存量,在您的情況下為3個int變量
但是它不會在它創建的指針上創建一個邊界(在您的情況下是ptr)。 因此您只需增加指針即可訪問未分配的內存。 那就是您的情況。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.