一、OpenSSL内存分配
普通用户在使用内存时,比较容易犯的错误就是内存溢出。当普通用户加载内存分配和释放函数时,查寻内存溢出较为繁琐。OpenSSL提供了内置的内存分配/释放函数。假如普通用户完全加载OpenSSL的内存分配和释放函数,能够 便捷的找出内存溢出点
OpenSSL分配内存时,在其内部维护1个内存分配哈希表,用作储放已经分配但未释放的内存信息:
当普通用户申请内存分配时,在哈希表中加入该项信息
释放内存时删掉该信息
当普通用户利用OpenSSL函数查寻内存溢出点时,只需查询该哈希表即可,普通用户利用OpenSSL回调函数还能处理那些泄露的内存
此文介绍的OpenSSL代码属于1.1.1g版本的,不同版本之间的接口名称可能不同
OpenSSL供普通用户加载的内存分配等函数关键在crypto/mem.c中实现,其内置的分配函数在crypto/mem_dbg.c中实现。默认情况下mem.c中的函数调用mem_dbg.c中的实现。假如普通用户实现了自己的内存分配函数以及查寻内存溢出的函数,能够 利用加载CRYPTO_set_mem_functions函数和CRYPTO_set_mem_debug_functions函数来设置
OPENSSL_NO_CRYPTO_MDEBUG宏定义
在OpenSSL中有个OPENSSL_NO_CRYPTO_MDEBUG宏定义,用于输出内存使用情况的,默认编译是没有打开的,需要重新编译库才可以,执行config时增加参数:enable-crypto-mdebug enable-crypto-mdebug-backtrace
如果没有这个宏,下面的CRYPTO_xxx()系列API可能都不能使用
例如,下面我们重新对openssl库进行配置、编译、安装
# 配置 ./config enable-ssl-trace enable-crypto-mdebug enable-crypto-mdebug-backtrace # 清除之前的编译内容 make clean # 再次编译 make # 安装 sudo make install
二、相关数据结构
struct app_mem_info_st
/*- * For application-defined information (static C-string `info‘) * to be displayed in memory leak list. * Each thread has its own stack. For applications, there is * OPENSSL_mem_debug_push("...") to push an entry, * OPENSSL_mem_debug_pop() to pop an entry, */ struct app_mem_info_st { CRYPTO_THREAD_ID threadid; const char *file; int line; const char *info; struct app_mem_info_st *next; /* tail of thread‘s stack */ int references; } APP_INFO;
/* memory-block description */ struct mem_st { void *addr; int num; const char *file; int line; CRYPTO_THREAD_ID threadid; unsigned long order; time_t time; APP_INFO *app_info; #ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE void *array[30]; size_t array_siz; #endif };
OpenSSL内存分配数据结构是一个内部数据结构,定义在crypto/mem_dbg.c中
各项意义如下:
addr:分配内存的地址
num:分配内存的大小
file:分配内存的文件
line:分配内存的行号
thread:分配内存的线程ID
order:第几次内存分配
time:内存分配时间
app_info:用于存放用户应用信息,为一个链表,里面存放了文件、行号以及线程ID等信息
references:被引用次数