2013-01-17 45 views
3

我知道如何使用malloc()free()來分配內存,但是還有一個標準的C函數來檢查剩餘的內存量,所以我可以定期調用它來確保我的代碼沒有內存泄漏?C - 檢查可用的公羊?

我唯一能想到的就是在無限循環中調用malloc(1),直到它返回一個錯誤,但是不應該有更有效的方法嗎?

+1

爲什麼不直接使用的valgrind在你的程序檢查是否漏水? – Mike

+2

請注意,在無限循環中調用malloc可能永遠不會失敗,因爲大多數系統僅在_first touch_上分配內存。 – Ben

+0

相關:http://stackoverflow.com/questions/2513505/how-to-get-available-memory-cg –

回答

6

不,沒有標準的C函數來做到這一點。有一些特定於平臺的功能可用於執行某些類型的查詢(如工作集大小),但這些功能可能不會有幫助,因爲有時已正確使用內存free()d仍被認爲由操作系統分配因爲malloc實現可能會將釋放的內存保留在池中。

如果您想檢查內存泄漏情況,我強烈建議您使用像Valgrind這樣的工具,它可以在各種虛擬機中運行程序,並可以跟蹤內存泄漏以及其他功能。

如果您在Windows上運行,則可以使用_CrtDbgReport和/或_CrtSetDbgFlag來檢查內存泄漏。

+0

該程序是在Cortex M0 CPU上運行的固件,以及使用了大量ARM特定的調用/指令,所以我認爲很難分析Valgrind,並且我沒有足夠的內存來運行我自己的代碼,更不用說添加虛擬機了。 – Muis

+2

在這種情況下,測量在執行開始時你擁有多少內存,並在'malloc'和'free'周圍編寫包裝函數,從你的起始點開始遞減和遞增,就像loreb在另一個答案中所表明的那樣。 –

2

如果你可以買得起#ifdef'ing一個調試版本(可能在模擬器!),你可以建立一個malloc/free的調試版本,跟蹤當前使用的字節數,並「打印」它會定期(再次 - 只在調試版本中,可能在仿真器下)在任何用於調試的輸出設備上(一個LED?),並查看它是否繼續增加。

標準的關鍵是要與新分配的內存分配在一起的sizeof(爲size_t)以上的要求,因而存儲大小 - 但如果你正在寫固件我想你已經知道了:)

所以...你有模擬器嗎?

編輯:我很習慣以GHz運行的計算機,它一開始並沒有出現在我身上,但當然你可以做的另一件事是隻計算分配的數量,而不是它們的大小 - 我無法想象這可能會佔用太多內存來運行。

1

如果在您的系統中malloc()始終分配物理內存,您可以重複調用malloc(),其大小不是1,而是通過連續冪爲2。這會更有效率。下面是如何做到這一點的一個例子。

另一方面,如果malloc()只分配虛擬地址空間而沒有將物理內存映射到虛擬地址空間,則這不會給你想要的。

示例代碼:

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

void* AllocateLargestFreeBlock(size_t* Size) 
{ 
    size_t s0, s1; 
    void* p; 

    s0 = ~(size_t)0^(~(size_t)0 >> 1); 

    while (s0 && (p = malloc(s0)) == NULL) 
    s0 >>= 1; 

    if (p) 
    free(p); 

    s1 = s0 >> 1; 

    while (s1) 
    { 
    if ((p = malloc(s0 + s1)) != NULL) 
    { 
     s0 += s1; 
     free(p); 
    } 
    s1 >>= 1; 
    } 

    while (s0 && (p = malloc(s0)) == NULL) 
    s0 ^= s0 & -s0; 

    *Size = s0; 
    return p; 
} 

size_t GetFreeSize(void) 
{ 
    size_t total = 0; 
    void* pFirst = NULL; 
    void* pLast = NULL; 

    for (;;) 
    { 
    size_t largest; 
    void* p = AllocateLargestFreeBlock(&largest); 

    if (largest < sizeof(void*)) 
    { 
     if (p != NULL) 
     free(p); 
     break; 
    } 

    *(void**)p = NULL; 

    total += largest; 

    if (pFirst == NULL) 
     pFirst = p; 

    if (pLast != NULL) 
     *(void**)pLast = p; 

    pLast = p; 
    } 

    while (pFirst != NULL) 
    { 
    void* p = *(void**)pFirst; 
    free(pFirst); 
    pFirst = p; 
    } 

    return total; 
} 

int main(void) 
{ 
    printf("Total free: %zu\n", GetFreeSize()); 
    printf("Total free: %zu\n", GetFreeSize()); 
    printf("Total free: %zu\n", GetFreeSize()); 
    printf("Total free: %zu\n", GetFreeSize()); 
    printf("Total free: %zu\n", GetFreeSize()); 
    return 0; 
} 

輸出(ideone):

Total free: 266677120 
Total free: 266673024 
Total free: 266673024 
Total free: 266673024 
Total free: 266673024