博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
openssl内存分配,查看内存泄露
阅读量:5789 次
发布时间:2019-06-18

本文共 3115 字,大约阅读时间需要 10 分钟。

openssl内存分配 

用户在使用内存时,容易犯的错误就是内存泄露。当用户调用内存分配和释放函数时,查找内存泄露比较麻烦。openssl提供了内置的内存分配/释放函数。如果用户完全调用openssl的内存分配和释放函数,可以方便的找到内存泄露点。openssl分配内存时,在其内部维护一个内存分配哈希表,用于存放已经分配但未释放的内存信息。当用户申请内存分配时,在哈希表中添加此项信息,内存释放时删除该信息。当用户通过openssl函数查找内存泄露点时,只需查询该哈希表即可。用户通过openssl回调函数还能处理那些泄露的内存。 
openssl供用户调用的内存分配等函数主要在crypto/mem.c中实现,其内置的分配函数在crypto/mem_dbg.c中实现。默认情况下mem.c中的函数调用mem_dbg.c中的实现。如果用户实现了自己的内存分配函数以及查找内存泄露的函数,可以通过调用CRYPTO_set_mem_functions函数和CRYPTO_set_mem_debug_functions函数来设置。下面主要介绍了openssl内置的内存分配和释放函数。 
5.2 内存数据结构 
openssl内存分配数据结构是一个内部数据结构,定义在crypto/mem_dbg.c中。如下所示: 
typedef struct app_mem_info_st 
unsigned long thread; 
const char *file; 
int line; 
const char *info; 
struct app_mem_info_st *next; /* tail of thread's stack */ 
int references; 
} APP_INFO; 
typedef struct mem_st 
void *addr; 
int num; 
const char *file; 
int line; 
unsigned long thread; 
unsigned long order; 
time_t time; 
APP_INFO *app_info; 
} MEM; 
各项意义: 
addr:分配内存的地址。 
num:分配内存的大小。 
file:分配内存的文件。 
line:分配内存的行号。 
thread:分配内存的线程ID。 
order:第几次内存分配。 
time:内存分配时间。 
app_info:用于存放用户应用信息,为一个链表,里面存放了文件、行号以及线程ID等信息。 
references:被引用次数。 
5.3 主要函数 
1) CRYPTO_mem_ctrl 
本函数主要用于控制内存分配时,是否记录内存信息。如果不记录内存信息,将不能查找内存泄露。开启内存记录调用CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON),关闭内存记录调用CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF)。一旦CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON)被调用,直到用户调用CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF)前,用户 所有的opessl内存分配都会被记录。 
2) CRYPTO_is_mem_check_on 
查询内存记录标记是否开启。 
3) CRYPTO_dbg_malloc 
本函数用于分配内存空间,如果内存记录标记开启,则记录用户申请的内存。当需要记录内存信息时,该函数本身也需要申请内存插入哈希表,为了防止递归申请错误,它申请内存记录信息前必须暂时关闭内存记录标记,申请完毕再放开。 
4) CRYPTO_dbg_free 
释放内存,如果内存记录标记开启,还需要删除哈希表中对应的记录。 
5) CRYPTO_mem_leaks 
将内存泄露输出到BIO中。 
6) CRYPTO_mem_leaks_fp 
将内存泄露输出到FILE中(文件或者标准输出),该函数调用了CRYPTO_mem_leaks。 
7) CRYPTO_mem_leaks_cb 
处理内存泄露,输入参数为用户自己实现的处理内存泄露的函数地址。该函数只需要处理一个内存泄露,openssl通过lh_doall_arg调用用户函数来处理所有记录(泄露的内存)。 
5.4 编程示例 
1)示例1 
#include <string.h> 
#include <openssl/crypto.h> 
int main() 
char *p; 
int i; 
p=OPENSSL_malloc(4); 
p=OPENSSL_remalloc(p,40); 
p=OPENSSL_realloc(p,32); 
for(i=0;i<32;i++) 
memset(&p[i],i,1); 
/* realloc时将以前的内存区清除(置乱) */ 
p=OPENSSL_realloc_clean(p,32,77); 
p=OPENSSL_remalloc(p,40); 
OPENSSL_malloc_locked(3); 
OPENSSL_free(p); 
return 0; 
上述示例使用了基本的openssl内存分配和释放函数。 
OPENSSL_malloc: 分配内存空间。 
OPENSSL_remalloc: 重新分配内存空间。 
OPENSSL_realloc_clean: 重新分配内存空间,将老的数据进行拷贝,置乱老的数据空间并释放。 
OPENSSL_malloc_locked 与锁有关。 
OPENSSL_free: 释放空间。 
2)示例2 
include <openssl/crypto.h> 
#include <openssl/bio.h> 
int main() 
char *p; 
BIO *b; 
CRYPTO_malloc_debug_init(); 
CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL); 
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); 
p=OPENSSL_malloc(4); 
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF); 
b=BIO_new_file("leak.log","w"); 
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); 
CRYPTO_mem_leaks(b); 
OPENSSL_free(p); 
BIO_free(b); 
return 0; 
}

void InitLeaks()

{

CRYPTO_malloc_debug_init();
CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
}
void LogLeaks()
{
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF); 
BIO *bLog=BIO_new_file("D:/leak.log","w");
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); 
CRYPTO_mem_leaks(bLog);
BIO_free(bLog); 
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF);
}

 

From:

转载于:https://www.cnblogs.com/coolYuan/p/8962310.html

你可能感兴趣的文章
C++中指针和引用的区别
查看>>
簡單分稀 iptables 記錄 udp 微軟 138 端口
查看>>
Java重写equals方法和hashCode方法
查看>>
Spark API编程动手实战-07-join操作深入实战
查看>>
H3C-路由策略
查看>>
centos 修改字符界面分辨率
查看>>
LNMP之Mysql主从复制(四)
查看>>
阅读Spring源代码(1)
查看>>
grep 命令
查看>>
JS二维数组的声明和使用
查看>>
v$archive_gap dg dataguard 断档处理 scn恢复
查看>>
问责IT风险管理:CIO需关注两个重点
查看>>
Winform打包发布图解
查看>>
PDF文件怎么编辑,超简单的方法
查看>>
EasyUI基础入门之Easyloader(载入器)
查看>>
Uva 839 Not so Mobile
查看>>
30款超酷的HTTP 404页面未找到错误设计
查看>>
程序猿必备 MyEclipse2013-2014系列
查看>>
java中ArrayList 、LinkList区别
查看>>
Spring ’14 Wave Update: Installing Dynamics CRM on Tablets for Windows 8.1
查看>>