2017-07-26 69 views
4

這裏是我使用的代碼:是malloc()初始化分配數組爲零?

#include <stdio.h> 
#include <stdlib.h> 

int main() { 
    int *arr; 
    int sz = 100000; 
    arr = (int *)malloc(sz * sizeof(int)); 

    int i; 
    for (i = 0; i < sz; ++i) { 
     if (arr[i] != 0) { 
      printf("OK\n"); 
      break; 
     } 
    } 

    free(arr); 
    return 0; 
} 

程序不打印OKmalloc不應該將分配的內存初始化爲零。這是爲什麼發生?

+7

內存的內容是* indeterminate *。它可能看起來是隨機的。或者它可能全部爲零。你根本不知道事先。 –

+2

*「程序不打印OK,malloc不應該將分配的內存初始化爲零。」* - 它也不能保證*不是全部爲零。無論哪種方式,通過讀取不確定的值,您的程序具有未定義的行爲。你無法期待任何事情。 – StoryTeller

+0

此外,調試構建可能實際上會導致您分配的內存甚至局部變量被初始化。使內存和指針問題更易於檢測。 –

回答

8

malloc手冊頁說:

的malloc()函數函數分配size個字節,並返回一個指針 分配的內存。 內存未初始化。如果大小爲0,則 ,則malloc()返回NULL,或者稍後可以將 成功傳遞給free()的唯一指針值。

所以,malloc()返回未初始化內存,其內容是不確定的。

if (arr[i] != 0) 

在你的程序中,你曾經試圖訪問一個內存塊,這是調用未定義行爲的內容。

5

malloc不應該將分配的內存初始化爲零。

malloc分配的內存未初始化。這些地點的價值是不確定的。在這種情況下,如果該位置的值是該類型的陷阱表示,則訪問該內存可能會導致未定義的行爲。

n1570-§6.2.6.1(P5):

某些對象表示不一定表示該對象類型的值。如果一個對象的存儲值有這樣的表示,並且被一個沒有字符類型的左值表達式讀取,那麼這個行爲是不確定的。 [...]

和腳註表示:

因此,自動變量可以被初始化爲陷阱表示,而不會導致未定義的行爲,但該變量的值不能被使用,直到一個適當的值存儲在其中。

如果行爲不確定,則可以預料沒有什麼好處。您可能會得到預期的結果,也可能得不到預期的結果。

2

void *malloc(size_t size)只是應該放在指定的空間量。就這樣。無法保證在該空間中會出現什麼。

從man頁面引用:

malloc()函數分配size個字節,並返回一個指針 分配的內存。內存未初始化。如果size爲0, 則malloc()返回NULL,或者返回一個唯一的指針值,後面的 可以成功傳遞給free()

除了calloc(),您可以使用memset()函數來清零內存塊。

2

malloc不應該將分配的內存初始化爲零。這是爲什麼發生?

這是40多年前的設計。

但是,同時創建了calloc()函數,將分配的內存初始化爲零,它是爲陣列分配內存的推薦方式。

行:

arr = (int *)malloc(sz * sizeof(int)); 

應改爲:

arr = calloc(sz, sizeof(int)); 

如果是從一本舊書它教學習C你總是投以malloc()calloc()(一void *)返回的值到您分配值的變量類型(您的案例中爲int *)。如果將由malloc()calloc()返回的值直接分配給變量,則這已過時,現代版本的C不需要再進行強制轉換。

+1

GCC文檔:_除了賦值操作符_以外的其他上下文中需要強制轉換。 –

+0

@RyanB。 - GCC在這裏不符合C標準。 'void *'可以隱式轉換爲所有對象類型。不需要強制轉換。 – StoryTeller

2

從C標準7.22.3.4:

梗概

#include <stdlib.h> 
void *malloc(size_t size); 

說明

malloc函數爲一個對象,其大小分配空間由大小指定 並且其價值不確定。

值爲不確定。所以,每個編譯器都可以自由地表達它的想法。例如,在Microsoft Visual C++中,在Debug模式下,malloc()分配的內存區域全部設置爲0xCDCDCDCD,並且在Release模式下它是隨機的。在現代版本的GCC中,如果您不啓用代碼優化,則將其設置爲0x000000,否則將其設置爲隨機值。我不知道其他編譯器,但你明白了。

0

您第一次打電話給malloc(3)時,它會要求操作系統爲堆空間獲取內存。

出於安全原因,unix/linux內核(以及許多其他操作系統)通常會將要提供給進程的頁面內容歸零,因此沒有進程可以訪問該內存的先前內容並使用它進行惡意操作(如搜索舊密碼或類似的東西)。

如果您執行多次內存分配和釋放,malloc模塊重新使用之前的內存時,您會看到來自malloc(3)的垃圾。