2009-09-17 76 views
3

如何通過使用免費名稱編寫包裝函數來解決雙重空閒問題,以便我不需要更改源代碼中的每個免費呼叫?雙免費問題

+0

相關:http://stackoverflow.com/questions/678254/c-function-conflict – dmckee 2009-09-17 15:04:44

+0

也相關:http://stackoverflow.com/questions/617554/override-a-function-call-in-c – dreamlax 2009-09-18 09:25:25

+0

對不起,在那裏吹着我自己的號角 – dreamlax 2009-09-18 09:26:04

回答

8

不要做

一個簡單的方法是定義你的包裝功能和#定義自由打電話給你的函數。

#undef free 
#define free(x) wrapper_free(x) 
/* ... */ 
int *data = malloc(42); 
free(data); /* effectively calls wrapper_free(data) */ 

但是...... 不這樣做!

+2

您應將defenition之前做一個'和#undef free':標準C允許STDLIB功能進行的方法,另外作爲宏 – Christoph 2009-09-17 14:59:53

+0

@pmg實現你能解釋一下爲什麼不呢? – Gewure 2017-03-14 13:52:56

+1

@gewure:'free()'有一個非常精確的定義。從長遠來看,用別的東西代替它肯定會傷害到你(你會比你想象的更快地忘記替換)。尤其如果您在頭文件中提供「重定義」。 – pmg 2017-03-14 17:01:20

28

不要這樣做。

不,真的。修復實際問題。一旦在指針上調用了空閒()之後,代碼應該由而不是由於任何原因持有它。將它清空,所以你不能再釋放它;這將會導致由stale指針解引用導致的任何其他問題也可見。

+6

+1將指針設置爲NULL。這實際上是最簡單的解決方案,永遠不會雙倍免費。無論如何,編寫一個執行'free()'的自定義'my_free()',然後將指針設置爲NULL似乎是確保這一點的最簡單方法。但是,這涉及代碼更改:-) – Joey 2009-09-17 14:31:25

+0

關於包裝器functino的好處,它負責將指針歸零。有些語言甚至包含這些內容,而使用它們總是一個好習慣。 Delphi對象有一個free()方法,但最好使用FreeAndNil()全局函數。當指針已經爲空時,它也不會拋出錯誤。 – 2009-09-17 14:39:52

+9

@Chris:是什麼讓你認爲'free(NULL)'引發錯誤? ANSI標準,第4.10.3.2節:「如果ptr是空指針,則不會發生任何操作。」 – Christoph 2009-09-17 14:50:24

1

我同意其他職位說,你不應該。主要的是,讓人們看看你的代碼並試圖弄清楚發生了什麼(當他們習慣於只看到釋放內存的空閒時)會更困惑。

如果你正在尋找一行代碼,可以讓你釋放和清除指針,我建議使用一個宏,儘管還有其他方法來做到這一點(創建一個方法,需要一個指針指向你的指針)。

#define FREEANDCLEAR(pointer)\ 
{\ 
    free(pointer);\ 
    pointer = 0;\ 
} 

編輯 作爲克里斯托弗在評論中提到,你也可以確保用戶使用宏像一個函數(用做結尾用分號線,而像這樣:

#define FREEANDCLEAR(pointer)\ 
do {\ 
    free(pointer);\ 
    pointer = 0;\ 
} while(0) 

將執行一次,並要求結束分號。

+2

沒有必要檢查'if(pointer)'''free(NULL)'是否有效並且什麼也不做;此外,您可能想在'do..while與包裝這個()'循環來獲取函數的語法 – Christoph 2009-09-17 14:42:13

+0

感謝克里斯託弗,我如果取消了,用在DO增加了第二個實現! – 2009-09-17 15:10:57

0

去翻答案,計算器問題,"Write your own memory manager"

在這些答案中使用這些工具或技術將允許您使用內存管理器來檢查這些類型的問題,以便您可以識別並修復這些問題(對於您的問題,許多其他答案表明,使用某些東西並不是一個好主意像這是一個解決方法)。

7

以下代碼截取對malloc()realloc()calloc()進行日誌記錄的調用。

當調用free()時,它檢查內存是否被預先分配了其中一個函數。否則,程序將被終止。釋放空指針將被報告,但執行將繼續。

頁眉memdebug.h

#undef free 
#define free(PTR) memdebug_free(PTR, #PTR, __FILE__, __func__, __LINE__) 

#undef malloc 
#define malloc(SIZE) memdebug_log(malloc(SIZE)) 

#undef realloc 
#define realloc(PTR, SIZE) memdebug_log(realloc(PTR, SIZE)) 

#undef calloc 
#define calloc(COUNT, SIZE) memdebug_log(calloc(COUNT, SIZE)) 

#ifndef MEMDEBUG_H 
#define MEMDEBUG_H 

extern void memdebug_free(void *ptr, const char *ptr_arg, const char *file, 
    const char *func, int line); 
extern void *memdebug_log(void *ptr); 

#endif 

來源memdebug.c

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

#ifndef MEMDEBUG_TABLE_SIZE 
// log 16k allocations by default 
#define MEMDEBUG_TABLE_SIZE 0x4000 
#endif 

static void *alloc_table[MEMDEBUG_TABLE_SIZE]; 
static size_t top; 

void *memdebug_log(void *ptr) 
{ 
    assert(top < sizeof alloc_table/sizeof *alloc_table); 
    alloc_table[top++] = ptr; 
    return ptr; 
} 

void memdebug_free(void *ptr, const char *ptr_arg, const char *file, 
    const char *func, int line) 
{ 
    if(!ptr) 
    { 
     fprintf(stderr, 
      "%s() in %s, line %i: freeing null pointer `%s` -->continue\n", 
      func, file, line, ptr_arg); 

     return; 
    } 

    for(size_t i = top; i--;) 
    { 
     if(ptr == alloc_table[i]) 
     { 
      free(ptr); 
      --top; 
      if(i != top) alloc_table[i] = alloc_table[top]; 
      return; 
     } 
    } 

    fprintf(stderr, 
     "%s() in %s, line %i: freeing invalid pointer `%s`-->exit\n", 
     func, file, line, ptr_arg); 

    exit(EXIT_FAILURE); 
} 
+0

+1,這應該適用於嵌入式環境或valgrind不可用時的其他情況。 – 2009-09-17 23:22:25

1

除了所有其他的答案和參考內存管理的研究與開發等。

當雙自由存在這樣的指示,事情並沒有按照正確的順序完成的代碼等錯誤發生

當我大約10年前開始使用Java,大家都稱讚Java的,因爲你沒有不得不煩擾新/刪除。

我很困擾(因爲我是用C/C++開發的),因爲除了malloc/free之外,突然間所有的open/close,create/destroy,鎖定/解鎖模式都以多種方式出現可能會被打破,因爲大家都認爲所有清理都是自動的。

所以當你有這些問題,你可能有其他的問題遲早的事。資源不足,數據庫連接被佔用,文件鎖定在文件系統上。

雙人自由是你的程序不具有良好的結構的信號,被分配在一個層e.g的事情,而在另一個釋放。