簡體   English   中英

我的malloc函數分配的次數超出了我的預期

[英]Is my malloc function allocating more than I intend to

這是我正在嘗試運行的代碼。 malloc函數分配800個字節。

void DynamicMemoryAllocationUsingMalloc()
{
    int* p,i;
    if((p = (int*) malloc(800)) == NULL)
    {
        printf("\n Out of Memory \n");
        exit(0);
    }

    for(i =0;i < 800;i++)
    {
        printf(" 0x%x", (p + i));
        printf(" %d\n", *(p + i));

    }
}

但是在我打印地址的for循環中,我能夠安全地跳過800個內存位置(使用整數指針p ),每個4字節長(整數的大小),相當於3200字節。 這是怎么可能的,或者我很幸運沒有得到訪問沖突錯誤,即使我實際上進入了我尚未分配給我的程序的內存區域? 我看到垃圾寫在所有內存位置的原因顯而易見,因為我沒有將這些內存位置設置為任何內容。

注意 :它是在Windows 7上運行的C程序。

這是怎么可能的,或者我很幸運沒有得到訪問沖突錯誤,即使我實際上進入了我尚未分配給我的程序的內存區域?

代碼到達printf(" %d\\n", *(p + 200)); 是試圖讀取外部分配的內存。 這是未定義的行為 UB。

UB是UB。 它可能每天都會發生,或者在下次運行時更改。


你不幸運。 幸運的是你的代碼會在那里停止。

即使讀取未初始化的int數據也是UB。 因此,只要printf(" %d\\n", *(p + 0));代碼就有UB(或者可能是實現定義printf(" %d\\n", *(p + 0)); IAC,代碼可以在那里停止。


我的malloc函數分配的次數超過了我的意圖嗎?

這是棘手的一點。 調用UB的代碼會產生可疑的結果。 沒有UB的代碼沒有標准的方法來測試問題。 確定這一點的唯一非UB方式是庫是否提供了具有答案的函數。

printf("True size %lu\n", (unsigned long) True_size(p));

注意:OP斷言int是4個字節。

它的工作原因可能是因為您沒有超出當前為該進程分配的內存范圍。 現代系統通常將內存分配給4千字節的進程。 您的第一次分配可能在頁面的開頭,而您正在窺探的內存可能位於該第一頁的未分配的剩余部分中。

操作系統無法檢測到無效的內存訪問,除非它們超出為您的進程分配的內存范圍。 就操作系統而言,它為您的流程提供了頁面和流程正在使用它。 它不關心你的進程使用的malloc例程是否說你的程序“擁有”那個內存。

在獲得訪問沖突之前,查看您可以閱讀的內容可能是一個有趣的實驗。 在嘗試閱讀之前,只需循環並打印每個地址。

但是在我打印地址的for循環中,我能夠安全地跳過800個內存位置(使用整數指針p),每個4字節長(整數的大小),相當於3200字節。

我猜“安全”你的意思是程序不會崩潰。 當應用於航空旅行時,這是一個正確的定義,但不適合計算機程序。

這是怎么可能的,或者我很幸運沒有得到訪問沖突錯誤,即使我實際上進入了我尚未分配給我的程序的內存區域?

通過訪問未分配的內存,您的程序會顯示未定義的行為。 認識到這個問題,你會受到贊揚。 但是,引用@KerrekSB,“未定義的行為是未定義的”。 一般來說,您不能假設未定義行為的任​​何特定表現。

例如,如果您的程序碰巧崩潰,並且存在訪問沖突,那么您可以確定它已經展示了未定義的行為,因為C沒有定義任何產生該行為的方法。 但僅僅因為它似乎做了你所期望的並不意味着它的行為是定義的。 如果沒有定義,那么一般來說,你也不能確信它是否一致。

所以基本上,是的,你很幸運。 或者也許不走運。 我自己,我寧願讓程序崩潰,以便我收到警報。

這是一個未定義行為的例子。 從邏輯上講,這個程序應該打破。 但它並不是因為過程映像有一些額外的空間,你可以在沒有操作系統發送段錯誤的情況下溢出。 我的意思是,不是去800,而是上升到1000,10000,等等。 最終,您將在任意數量的迭代中獲得段錯誤。

你可以這么高的原因是因為你的程序在ram中有很多開銷,這個開銷被允許溢出。

C標准答案 :訪問超出已分配內存的內存會導致未定義的行為。

現實世界的答案 :您的程序使用malloc()分配內存,malloc()從操作系統(在本例中為Windows)中提供內存。 但是,每次malloc()調用都不會導致對操作系統的調用。 實際上,Malloc通常會分配比現在需要的內存更多的內存,然后將中斷至少是您請求的大小的塊。 這是出於性能原因而完成的,因為每次調用操作系統都會產生一些開銷。 此外,還有一個最小“頁面大小”,它是可以從操作系統分配的最小內存單元。 4096字節是典型的頁面大小。

因此,在您的情況下,您正在訪問malloc已從系統配置但尚未分配使用的內存。 您應該避免這種情況,因為下一次調用malloc可能會導致內存被分配用於其他目的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM