//申請記憶體的執行緒號
const char *file;//申請記憶體的檔名
int line;//申請記憶體的行號
/* tail of thread's stack */
int references;//被引用的次數
這個結構體是用來記錄使用者申請的記憶體資訊的。
typedef struct mem_st
mem;
這個結構是用來描述記憶體塊的,使用者每使用openssl_malloc成功申請一次記憶體,就會產生乙個這樣的結構體,並把這個結構體存入雜湊表mh中。
下面,我想從兩個函式(openssl_malloc和openssl_free)來說明openssl在記憶體管理方面是怎麼做的,其實openssl 只是給我們常用的malloc和free加了乙個外殼,這使得使用者在申請記憶體時,它可以把使用者的資訊記錄下來並存入乙個雜湊表中。
函式openssl_maloc
函式openssl_malloc是openssl中在申請記憶體時,用來代替malloc的。其實,openssl_malloc是乙個巨集定義,定義在檔案/cypto/crypto.h中:
#define openssl_malloc(num) crypto_malloc((int)num,__file__,__line__)
從這裡,很明顯可以看出,當我們呼叫openssl_malloc時,openssl可以通過巨集__file__和__line__很方便地把檔名和 行號錄下來。那麼,函式crypto_malloc又是什麼呢?它是乙個函式,定義在檔案/crypto/mem.c中:
void *crypto_malloc(int num, const char *file, int line)
ret = malloc_ex_func(num,file,line);
//其實記憶體就是在這一句被分配的
#ifdef levitte_debug_mem
fprintf(stderr, "levitte_debug_mem: > 0x%p (%d)/n", ret, num);
#endif
if (malloc_debug_func != null)
malloc_debug_func(ret, num, file, line, 1);
/* create a dependency on the value of 'cleanse_ctr' so our memory
* sanitisation function can't be optimised out. nb: we only do
* this for >2kb so the overhead doesn't bother us. */
if(ret && (num > 2048))
((unsigned char *)ret)[0] = cleanse_ctr;
return ret;
}從上的函式,我們可以看出記憶體分配是通過malloc_ex_func完成的,在這個函式的上下方,分別呼叫了兩次malloc_debug_func。
我們先說malloc_ex_func,它是乙個函式指標,它的定義在檔案/crypto/mem.c中:
static void *(*malloc_func)(size_t) = malloc;
static void *default_malloc_ex(size_t num, const char *file, int line)
static void *(*malloc_ex_func)(size_t, const char *file, int line)
= default_malloc_ex;
其實,函式malloc_ex_func就是malloc。
我們再來看函式,malloc_debug_func,它也是乙個函式指標,它的定義在檔案/crypto/mem.c中:
static void (*malloc_debug_func)(void *,int,const char *,int,int) = null;//把使用者申請記憶體的資訊存入結構體m中
m->addr=addr;
m->file=file;
m->line=line;
m->num=num;
if (options & v_crypto_mdebug_thread)
m->thread=crypto_thread_id();
else
m->thread=0;
if (order == break_order_num)
if ((mm=(mem *)lh_insert(mh,(char *)m)) != null)
break;
}return;
}看完上面的**,應該不難理解函式openssl_malloc的執行過程了,通過函式malloc_ex_func(也就是malloc)分配記憶體,通過函式crypto_malloc_dbg把使用者申請記憶體的資訊存入雜湊表mh中。
函式openssl_free
函式openssl_free是openssl在釋放記憶體時,用來代替free的。openssl_free是乙個巨集定義,定義在檔案/crypto/crypto.h中:
#define openssl_free(addr) crypto_free(addr)
我們再來看一下函式crypto_free,實現在檔案/crypto/mem.c中:
void crypto_free(void *str)
這裡,我們可以看到函式crypto_free和函式crypto_malloc的結構幾乎是一樣的。變數free_debug_func和變數free_func是兩個函式指標,定義在檔案/crypto/mem.c中:
static void (*free_func)(void *) = free;
static void (*free_debug_func)(void *,int) = null;
從函式crypto_malloc_debug_init和函式crypto_set_mem_debug_functions中可以看出,變數 free_debug_func的值應該為crypto_dbg_free,這個函式的定義在檔案/crypto/mem_dbg.c中:
void crypto_dbg_free(void *addr, int before_p)
break;
case 1:
break;}}
所以,當我們呼叫openssl_malloc申請記憶體,而沒有呼叫openssl_free釋放記憶體時,我們只需要遍歷雜湊表mh,就可以知道哪些記憶體還沒有被釋放。
用於輸出記憶體洩露資訊的函式,我們可以使用crypto_mem_leaks,這個函式把記憶體洩露的資訊輸出到乙個bio。
下面,我們來看一下openssl一些常用的記憶體管理的函式:
1. #define openssl_malloc(num) crypto_malloc((int)num,__file__,__line__)
2. #define openssl_strdup(str) crypto_strdup((str),__file__,__line__)
char *crypto_strdup(const char *str, const char *file, int line)
3. #define openssl_realloc(addr,num) crypto_realloc((char *)addr,(int)num,__file__,__line__)
此函式用法與realoc相同。
4. #define openssl_free(addr) crypto_free(addr)
5. void crypto_mem_leaks_fp(file *fp);
此函式的作用是把記憶體洩露資訊輸出到檔案fp,這個函式是通過crypto_mem_leaks實現的。
6. void crypto_mem_leaks(struct bio_st *bio);
此函式的作用是把記憶體洩露資訊輸出到bio。
7. void crypto_malloc_debug_init(void);
C 學習筆記之記憶體分配
靜態記憶體 staitc memory 儲存區域性static物件 類static資料成員 定義在任何函式之外的變數 棧記憶體 stack 儲存定義在函式內的非static物件 自由空間 free store 或稱堆記憶體 heap 儲存動態分配 即程式執行時分配 的物件 1.分配在靜態記憶體和棧記...
記憶體分配學習
1.儲存類別 被儲存的每個值都占用一更的物理記憶體,c語言把這樣的一塊記憶體叫做物件。乙個物件可以儲存乙個或多個值。乙個物件可能未存實際的值,但是在儲存適當的值時一定具有相應的大小。可以用儲存期來描述物件,用識別符號訪問物件。用作用於和鏈結藐視識別符號。1.1作用域 作用域描述程式中可訪問識別符號的...
動態分配記憶體(學習筆記11)
函式原型 stdlib.h void malloc size 分配size大小的記憶體,返回指向所分配記憶體的指標,分配不成功,返回null void calloc num element,length of element 分配num element length of element 大小的記憶...