openssl3.2 - crypto-mdebug被弃用后, 内存泄漏检查的替代方法

文章目录

openssl3.2 - crypto-mdebug被弃用后, 内存泄漏检查的替代方法

概述

调用openssl接口后, 如果用到了openssl对象, 需要释放, 否则会发生内存泄漏.

即使不是新手, 也不能保证释放函数都调用了. 想想我们自己写程序, new后, 没有delete的情况就知道, 可以理解.

谁能保证自己手搓的应用实现100%没内存泄漏呢?

看资料时, 发现openssl本身有这个检查库本身发生内存泄漏的特性, 大概就是申请内存时, openssl自己记录了一下, free内存时, 将对应记录删掉.

这样, 在程序退出前, 再调用一下内存分配记录列表接口, 就知道哪里的内存没释放.

那试试, 加入crypto-mdebug特性, 模拟一下内存泄漏(调用openssl_new(), 不调用openssl_free()), 看看啥效果.

笔记

查看特性列表

bash 复制代码
perl configdata.pm --dump > my_log.txt

查看my_log.txt, 就有openssl 特性列表.

有启用的特性列表, 也有被禁掉的特性列表.

如果要加入特性, 就看禁止列表中的特性.

怎么打开crypto-mdebug特性呢?

看Configure可知, 只要带上参数 enable-crypto-mdebug即可.

结合我最后实验可用的编译脚本, 加入 enable-crypto-mdebug

openssl3.2编译脚本 - 加入enable-crypto-mdebug

bash 复制代码
解开官方源码包

打开vs2019x64本地命令行, 选择管理员身份运行

cd /d D:\3rd_prj\crypt\openssl-3.2.0

set path=c:\nasm;%path%

perl Configure VC-WIN64A --debug enable-crypto-mdebug zlib-dynamic --with-zlib-include=D:\my_dev\lib\zlib_1d3 --with-zlib-lib=.\my_zlib_1d3.dll --prefix=c:\openssl_3d2 --openssldir=c:\openssl_3d2\common

nmake

手工拷贝, 将 my_zlib_1d3.dll 拷贝到以下4个目录
.\
.\apps
.\fuzz
.\test

nmake test

nmake install

手工拷贝
D:\my_dev\lib\zlib_1d3\my_zlib_1d3.dll => C:\openssl_3d2\bin\my_zlib_1d3.dll

归档
C:\openssl_3d2 剪切到自己的库目录 => D:\my_dev\lib\openssl_3d2

写个测试程序, 调用一下内存泄漏检查的相关接口, 看看能否编译过, 然后试试接口怎么用.

c 复制代码
/*!
* \file main.cpp
*/

#include "my_openSSL_lib.h"

#include <openssl/crypto.h> // for mem leak API

int main(int argc, char** argv)
{

	CRYPTO_mem_leaks(NULL);
	return 0;
}

/*!
编译错误
已启动重新生成...
1>------ 已启动全部重新生成: 项目: prj_template, 配置: Debug x64 ------
1>main.cpp
1>D:\my_dev\my_local_git_prj\study\openSSL\exp\call_mem_leak_API\main.cpp(12,2): error C4996: 'CRYPTO_mem_leaks': Since OpenSSL 3.0
1>已完成生成项目"prj_template.vcxproj"的操作 - 失败。
========== 全部重新生成: 成功 0 个,失败 1 个,跳过 0 个 ==========
*/

直接编译不过...

看官方说明 file:///D:/3rd_prj/crypt/openssl-3.2.0/doc/html/man3/OPENSSL_malloc.html

bash 复制代码
The following functions have been deprecated since OpenSSL 3.0, and can be hidden entirely by defining OPENSSL_API_COMPAT with a suitable version value, see openssl_user_macros(7):

 int CRYPTO_mem_leaks(BIO *b);
 int CRYPTO_mem_leaks_fp(FILE *fp);
 int CRYPTO_mem_leaks_cb(int (*cb)(const char *str, size_t len, void *u),
                         void *u);
 
 int CRYPTO_set_mem_debug(int onoff);
 int CRYPTO_mem_ctrl(int mode);
 int OPENSSL_mem_debug_push(const char *info);
 int OPENSSL_mem_debug_pop(void);
 int CRYPTO_mem_debug_push(const char *info, const char *file, int line);
 int CRYPTO_mem_debug_pop(void);
DESCRIPTION

看到官方说, 这些内存诊断函数已经弃用了, 用clang的检查代替(忘了是哪个文档了, 反正是官方文档中说的).

去看内存诊断函数的实现, 都是空的, 官方确实已经弃用了.

尝试将vs2019的工具链改为clang, 看不到效果, 且不能单步进入库函数内部.

用clang工具链编译, 可以编译过, 也可以运行, 不过无法进入调试版的pdb实现中.

bash 复制代码
已启动重新生成...
1>------ 已启动全部重新生成: 项目: prj_template, 配置: Debug x64 ------
1>main.cpp(12,2): warning : 'CRYPTO_mem_leaks' is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations]
1>D:\my_dev\lib\openssl_3d2\include\openssl/crypto.h(411,1): message : 'CRYPTO_mem_leaks' has been explicitly marked deprecated here
1>D:\my_dev\lib\openssl_3d2\include\openssl/macros.h(194,49): message : expanded from macro 'OSSL_DEPRECATEDIN_3_0'
1>D:\my_dev\lib\openssl_3d2\include\openssl/macros.h(44,22): message : expanded from macro 'OSSL_DEPRECATED'
1>prj_template.vcxproj -> D:\my_dev\my_local_git_prj\study\openSSL\exp\call_mem_leak_API\x64\Debug\prj_template.exe
1>'pwsh.exe' 不是内部或外部命令,也不是可运行的程序
1>或批处理文件。
1>已完成生成项目"prj_template.vcxproj"的操作。
========== 全部重新生成: 成功 1 个,失败 0 个,跳过 0 个 ==========

那就不用clang来编译.

看看有没有替代内存诊断的方法?

找到一个opensslAPI CRYPTO_get_alloc_counts(), 可以取当前内存分配次数.

将这个API封装一下, 卡在openssl应用函数外边, 就可以间接的知道是否有内存泄漏, 如果有opensslAPI调用引起的内存泄漏, 可以迅速的缩小排查范围.

main.cpp

c 复制代码
/*!
* \file main.cpp
*/

#include "my_openSSL_lib.h"

#include <openssl/crypto.h>

bool is_OSSL_mem_leak();
void test_mem_leak(bool b_have_mem_leak);

int main(int argc, char** argv)
{
	openssl_mdebug_begin();
	test_mem_leak(true);
	openssl_mdebug_end(true, false); // 如果需要断言, 参数2为true

	openssl_mdebug_begin();
	test_mem_leak(false);
	openssl_mdebug_end(true, true);

	/*
	run result

	test_mem_leak(test have mem leak)
	>> malloc_count = 0, realloc_count = 0, free_count = 0
	<< malloc_count = 1, realloc_count = 0, free_count = 0
	err : !!! mem leak happen
	test_mem_leak(test no mem leak)
	*/
	
	return 0;
}

void test_mem_leak(bool b_have_mem_leak)
{
	void* pBuf = NULL;

	printf("test_mem_leak(%s)\n", (b_have_mem_leak ? "test have mem leak" : "test no mem leak"));

	pBuf = OPENSSL_malloc(2);

	// do some task ...

	if (!b_have_mem_leak)
	{
		OPENSSL_free(pBuf);
		pBuf = NULL;
	}
}

my_openSSL_lib.h

c 复制代码
/*!
\file my_openSSL_lib.h
*/

#ifndef __MY_OPENSSL_LIB_H__
#define __MY_OPENSSL_LIB_H__

#ifdef __cplusplus
extern "C" {
#endif


#ifdef  _WIN32
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib") // for select()

#include <windows.h>

#include <stdbool.h>

#pragma comment(lib, "libcrypto.lib")
#pragma comment(lib, "libssl.lib")

#endif /* #ifdef  _WIN32 */

// --------------------------------------------------------------------------------
// 开关宏 - begin
// --------------------------------------------------------------------------------

#define MY_USE_APPLINK

// --------------------------------------------------------------------------------
// 开关宏 - END
// --------------------------------------------------------------------------------

typedef struct _tag_openssl_mem_counter{
	int malloc_count_begin;
	int realloc_count_begin;
	int free_count_begin;

	int malloc_count_end;
	int realloc_count_end;
	int free_count_end;
} TAG_OPENSSL_MEM_COUNTER;

void openssl_mdebug_begin();
bool openssl_mdebug_end(bool show_tip, bool b_assert);

#ifdef __cplusplus
}
#endif

#endif /* #ifndef __MY_OPENSSL_LIB_H__ */

my_openSSL_lib.c

c 复制代码
/*!
* \file D:\my_dev\my_local_git_prj\study\openSSL\nmake_test\test_c\prj_005_afalgtest.c\my_openSSL_lib.c
*/

#include "my_openSSL_lib.h"
#include "openssl/crypto.h" // for CRYPTO_get_alloc_counts

#include <assert.h>

#ifdef MY_USE_APPLINK
#include <openssl/applink.c> /*! for OPENSSL_Uplink(00007FF8B7EF0FE8,08): no OPENSSL_Applink */
#endif // #ifdef MY_USE_APPLINK

static TAG_OPENSSL_MEM_COUNTER gs_openssl_mdebug;

void openssl_mdebug_begin()
{
	CRYPTO_get_alloc_counts(&gs_openssl_mdebug.malloc_count_begin, &gs_openssl_mdebug.realloc_count_begin, &gs_openssl_mdebug.free_count_begin);
}

bool openssl_mdebug_end(bool show_tip, bool b_assert)
{
	bool b_rc = false;
	long lCntBegin = 0;
	long lCntEnd = 0;

	CRYPTO_get_alloc_counts(&gs_openssl_mdebug.malloc_count_end, &gs_openssl_mdebug.realloc_count_end, &gs_openssl_mdebug.free_count_end);
	lCntBegin = gs_openssl_mdebug.malloc_count_begin + gs_openssl_mdebug.realloc_count_begin - gs_openssl_mdebug.free_count_begin;
	lCntEnd = gs_openssl_mdebug.malloc_count_end + gs_openssl_mdebug.realloc_count_end - gs_openssl_mdebug.free_count_end;
	b_rc = (lCntBegin == lCntEnd);
	if (!b_rc && show_tip)
	{
		printf(">> malloc_count = %d, realloc_count = %d, free_count = %d\n", gs_openssl_mdebug.malloc_count_begin, gs_openssl_mdebug.realloc_count_begin, gs_openssl_mdebug.free_count_begin);
		printf("<< malloc_count = %d, realloc_count = %d, free_count = %d\n", gs_openssl_mdebug.malloc_count_end, gs_openssl_mdebug.realloc_count_end, gs_openssl_mdebug.free_count_end);
		printf("err : !!! mem leak happen\n");
	}

	if (b_assert)
	{
		assert(true == b_rc);
	}

	return b_rc;
}

备注

以后有机缘再查查怎么用clang来查openssl应用是否有内存泄漏.

查资料时, 很多情况下都不是想查就能查到的.

很多时候, 是心里带着问题, 查其他资料时, 突然给了启发, 才将以前的问题搞掉.

这种调用CRYPTO_get_alloc_counts()来间接的排查是否调用opensslAPI时, 是否没有成对的分配,释放内存.

没有那么直接和方便, 不过也算是一种方法了. 有总比没有强.

希望以后能找到其他更好的方法来定位opensslAPI调用时的内存泄漏点.

备注

openssl的编译检查, 测试用例还是很严格的.

对外提供的API, 都有测试程序.

CRYPTO_get_alloc_counts()这个API的调用, 也能找到至少一处.

用SI将openssl源码编译的目录中的能识别的东东都包进来搜索, 必然能看到测试用例或者API调用的痕迹.

如果某个API虽然定义, 但是官方源码编译目录的实现中都没有用到, 那么咱么就不能用这个API.

这招不行啊

今天正好写个测试程序, 用到了这种内存泄漏检测方法. 有断言, 不好使.

c 复制代码
int main(int argc, char** argv)
{
	BIO* bio = NULL;

	openssl_mdebug_begin();
    test_bio_mem_leak();
    // test_bio_new_mem_buf();
	openssl_mdebug_end(false, true);

	return 0;
}

void test_bio_mem_leak(void)
{
    BIO* bio = BIO_new_mem_buf("Hello World\n", 12);
    BIO_free(bio);
}

只能先关注这事, 以后再想办法了.

跟了一下openssl代码, 是产生默认库上下文中有很多openssl_malloc()引起的内存分配.

后续再看看, 自己显势调用产生销毁默认上下文的API, 是否可以继续用这种方法.

显势调用默认上下文也不行

c 复制代码
int main(int argc, char** argv)
{
    OSSL_LIB_CTX* _ossl_lib_ctx = NULL;
	BIO* bio = NULL;

    do {
        openssl_mdebug_begin();
        _ossl_lib_ctx = OSSL_LIB_CTX_get0_global_default();
        if (NULL == _ossl_lib_ctx)
        {
            assert(false);
            break;
        }

        test_bio_mem_leak();
        // test_bio_new_mem_buf();

        OSSL_LIB_CTX_free(_ossl_lib_ctx);
        openssl_mdebug_end(true, false); // 到这里, 还是报错
    } while (false);

	return 0;
}

void test_bio_mem_leak(void)
{
    BIO* bio = BIO_new_mem_buf("Hello World\n", 12);
    BIO_free(bio);
}

报错原因, openssl函数调用中, 会有其他默认的上下文建立会调用内存分配.

具体是啥函数, 要去单步.

这种用内存分配计数的方法, 不能真实的间接观察到openssl内部的内存泄漏, 做了一个没用的实验...

还是要老老实实的看官方例子, 手工调用对应API的释放函数.

找到一种还可以的解决方法, 现在看来可以准确观测到openssl内存泄漏点

openssl设计的可以, 预留了很多有用的API.

翻翻openssl提供的API, 找到了以下有用的API.

bash 复制代码
CRYPTO_get_mem_functions()
CRYPTO_set_mem_functions()
OPENSSL_init_crypto()
OPENSSL_cleanup()

这些可以用于辅助观测openssl内存泄漏点, 不止是openssl API, openssl内部发生的内存泄漏也能观测到(如果有的话)

内存泄漏观测的程序实现

main.cpp

c 复制代码
/*!
* \file main.cpp
*/

#include "my_openSSL_lib.h"
#include <openssl/crypto.h>
#include <openssl/bio.h>

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

#include "CMemHookRec.h"

void test_bio_mem_leak(bool b_have_mem_leak);

int main(int argc, char** argv)
{
	setvbuf(stdout, NULL, _IONBF, 0); // 清掉stdout缓存, 防止调用printf时阻塞

	// mem IF hook, 必须在执行任何openssl API之前替换
	mem_hook();

	// 自己的openssl接口应用
	test_bio_mem_leak(true);
	test_bio_mem_leak(false);

	// mem IF un hook, 必须在openssl结束后, 再恢复原始函数
	mem_unhook();

	/* run result, 如果有openssl应用接口没释放引起的内存泄漏, 有断言, stdout有输出
	一个openssl API引起的内存泄漏可能对应这多条内存分配记录, 不过排查范围缩小多了, 线索也清晰多了 
	结合对自己的openssl调用代码块的注释排除法, 很容易找到自己哪里没调用正确的openssl释放API.
		
	free map, g_mem_hook_map.size() = 4
	2AAA2F36560 128 crypto\bio\bio_lib.c:83
	2AAA2F4EC40 16 crypto\bio\bss_mem.c:111
	2AAA2FEA470 32 crypto\bio\bss_mem.c:119
	2AAA2FEAA10 32 crypto\buffer\buffer.c:35
	error : !!! find openssl call memory leak
	Assertion failed: false, file D:\my_dev\my_local_git_prj\soft\xx\src\case\exp002_mem_hook\main.cpp, line 57
	*/
	
	return 0;
}

void test_bio_mem_leak(bool b_have_mem_leak)
{
	BIO* bio = BIO_new_mem_buf("Hello World\n", 12);

	if (false == b_have_mem_leak)
	{
		BIO_free(bio);
	}
}

找内存泄漏时很方便, 只要在程序入口处调用mem_hook(), 然后自己正常调用openssl API, 程序结束前调用mem_unhook()

如果有openssl 释放API没调用引起的内存泄漏, 就会有断言.

如果是控制台程序, 就可以直接看到内存泄漏点.

如果不是控制台程序, 将mem_unhook()中的内存泄漏改写到其他输出(e.g. 文件).

这排查起来就容易多了.

CMemHookRec.h

c 复制代码
/*!
\file CMemHookRec.h
\note openssl 分配API hook 之后, 记录的内存分配记录
*/


#ifndef __CMEMHOOKREC_H__
#define __CMEMHOOKREC_H__

#include <cstdint>
#include <stdio.h>
#include <map>
#include <openssl/crypto.h>

#define SAFE_DELETE(p) \
do { \
    if (NULL != (p)) { \
        delete (p);\
    } \
    (p)=NULL; \
} while (0);

class CMemHookRec
{
public:
	void show_info();

public:
	uint64_t u64_addr;
	size_t num;
	const char* file;
	int line;

	uint64_t rec_sn;
};

void mem_hook();
void mem_unhook();

void* my_CRYPTO_malloc(size_t num, const char* file, int line);
void* my_CRYPTO_realloc(void* addr, size_t num, const char* file, int line);
void my_CRYPTO_free(void* ptr, const char* file, int line);
bool free_map();

#endif // #ifndef __CMEMHOOKREC_H__

CMemHookRec.cpp

c 复制代码
/// \file CMemHookRec.cpp

#include "CMemHookRec.h"
#include <assert.h>

void CMemHookRec::show_info()
{
	printf("entry sn = [%I64d],  %I64X %zu %s:%d\n", this->rec_sn, u64_addr, num, ((NULL != file) ? file : "NULL"), line);
}

std::map<uint64_t, CMemHookRec*> g_mem_hook_map;
typedef std::pair<uint64_t, CMemHookRec*> Map_Pair_mem_hook;
typedef std::map<uint64_t, CMemHookRec*>::iterator It_mem_hook;

// 		malloc_fn_org	0x00007ffb0796614f {libcrypto-3-x64.dll!CRYPTO_malloc}	void *(*)(unsigned __int64, const char *, int)
CRYPTO_malloc_fn malloc_fn_org = NULL;

// 		realloc_fn_org	0x00007ffb07967a1d {libcrypto-3-x64.dll!CRYPTO_realloc}	void *(*)(void *, unsigned __int64, const char *, int)
CRYPTO_realloc_fn realloc_fn_org = NULL;

// 		free_fn_org	0x00007ffb079631b1 {libcrypto-3-x64.dll!CRYPTO_free}	void(*)(void *, const char *, int)
CRYPTO_free_fn free_fn_org = NULL;

void mem_hook()
{
	int i_rc = 0;
	uint64_t u64_init_opt = 0;

	CRYPTO_get_mem_functions(&malloc_fn_org, &realloc_fn_org, &free_fn_org);
	CRYPTO_set_mem_functions(my_CRYPTO_malloc, my_CRYPTO_realloc, my_CRYPTO_free);

	// openssl init all
	OPENSSL_INIT_SETTINGS* _ossl_init_setting = OPENSSL_INIT_new();

	u64_init_opt = OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
		OPENSSL_INIT_ADD_ALL_CIPHERS |
		OPENSSL_INIT_ADD_ALL_DIGESTS |
		OPENSSL_INIT_LOAD_CONFIG |
		OPENSSL_INIT_ASYNC |
		OPENSSL_INIT_NO_ATEXIT;

	// 将openssl库中的静态初始化函数显势调用一下, 免得在我们手工调用API时(因为有些openssl对象或变量没初始化)自动调用静态初始化函数引起多余的非我们应用产生的内存分配
	// 初始化函数在应用中只能调用一次.
	i_rc = OPENSSL_init_crypto(u64_init_opt, _ossl_init_setting);
	assert(1 == i_rc);
}

void mem_unhook()
{
	// openssl uninit all
	// 只能调用一次
	OPENSSL_cleanup();

	// 必须在openssl cleanup之后调用map显示, 这样才能过滤掉系统自动分配的内存.
	// 如果map不为空, 这些记录才是我们自己应用没释放的内存
	// 在free_map()时, 如果看到多条未被释放的内存, 也一定是那么多个API调用没释放, 因为一条openssl API会对应者多个openssl_mallc(), e.g. BIO_new_mem_buf() 就有4个内存分配动作.
	if (!free_map())
	{
		printf("error : !!! find openssl call memory leak\r\n");
		assert(false);
		/* run result
		free map, g_mem_hook_map.size() = 4
		2AAA2F36560 128 crypto\bio\bio_lib.c:83
		2AAA2F4EC40 16 crypto\bio\bss_mem.c:111
		2AAA2FEA470 32 crypto\bio\bss_mem.c:119
		2AAA2FEAA10 32 crypto\buffer\buffer.c:35
		error : !!! find openssl call memory leak
		Assertion failed: false, file D:\my_dev\my_local_git_prj\soft\krgy_software_protect\src\case\exp002_mem_hook\main.cpp, line 57
		*/
	}

	CRYPTO_set_mem_functions(malloc_fn_org, realloc_fn_org, free_fn_org);
}

bool free_map()
{
	It_mem_hook it = g_mem_hook_map.end();
	size_t size = g_mem_hook_map.size();

	printf("free map, g_mem_hook_map.size() = %zd\n", size);
	for (it = g_mem_hook_map.begin(); it != g_mem_hook_map.end(); it++) {
		if (NULL != it->second) {
			it->second->show_info();
		}
		SAFE_DELETE(it->second);
	}
	g_mem_hook_map.clear();

	return (0 == size);
}

static uint64_t g_u64_malloc_cnt_all = 0;
void* my_CRYPTO_malloc(size_t num, const char* file, int line)
{
	void* p = NULL;
	It_mem_hook it;
	CMemHookRec* rec = NULL;

	p = malloc(num);
	if (NULL != p)
	{
		it = g_mem_hook_map.find((uint64_t)p);
		if (it != g_mem_hook_map.end()) {
			// printf("find key\n");
			assert(false);
		}
		else {
			// printf("not find key\n");
			rec = new CMemHookRec();
			if (NULL != rec)
			{
				rec->rec_sn = ++g_u64_malloc_cnt_all;
				rec->u64_addr = (uint64_t)p;
				rec->num = num;
				rec->file = file;
				rec->line = line;

				g_mem_hook_map.insert(Map_Pair_mem_hook(rec->u64_addr, rec));
			}
		}
	}

	return p;
}

void* my_CRYPTO_realloc(void* addr, size_t num, const char* file, int line)
{
	void* p = NULL;
	It_mem_hook it;
	CMemHookRec* rec = NULL;

	p = realloc(addr, num);
	if (NULL != p)
	{
		it = g_mem_hook_map.find((uint64_t)addr);
		if (it != g_mem_hook_map.end()) {
			// printf("find key\n");
			SAFE_DELETE(it->second);
			g_mem_hook_map.erase(it);
		}

		rec = new CMemHookRec();
		if (NULL != rec)
		{
			rec->rec_sn = ++g_u64_malloc_cnt_all;
			rec->u64_addr = (uint64_t)p;
			rec->num = num;
			rec->file = file;
			rec->line = line;

			g_mem_hook_map.insert(Map_Pair_mem_hook(rec->u64_addr, rec));
		}
	}
	return p;
}

void my_CRYPTO_free(void* ptr, const char* file, int line)
{
	It_mem_hook it;
	CMemHookRec* rec = NULL;

	if (NULL != ptr)
	{
		free(ptr);

		it = g_mem_hook_map.find((uint64_t)ptr);
		if (it != g_mem_hook_map.end()) {
			// printf("find key\n");
			SAFE_DELETE(it->second);
			g_mem_hook_map.erase(it);
		}
		else {
			// printf("not find key\n");
			assert(false);
		}
	}
}

备注

此笔记前面实验的CRYPTO_get_alloc_counts()方法, 在mem_hook中用不了了, 因为将内存分配函数换掉了.

不过, 可以在上面这个实验上改改, 不hook内存分配函数, 只用 OPENSSL_init_crypto() + OPENSSL_cleanup() + CRYPTO_get_alloc_counts(), 应该也能看到内存泄漏的计数, 但是看不到哪个文件哪行发生的泄漏.

因为这个想法不好, 我就没去再实验.

毕竟有多个解决方法, 只取最优的那个.

mem_hook()这个方法好, 能看到发生泄漏的具体库文件和行数, 排查起来可操作性强.

备注

将 void CMemHookRec::show_info()的输出改了一下, 上面的实验代码已经更新.

c 复制代码
void CMemHookRec::show_info()
{
	printf("entry sn = [%I64d],  %I64X %zu %s:%d\n", this->rec_sn, u64_addr, num, ((NULL != file) ? file : "NULL"), line);
}

这样的话, 等观测到内存泄漏时, 号码连续的就是一个openssl API的调用引起的内存泄漏, 更方便调试排查.

END

相关推荐
深耕AI12 天前
Win64OpenSSL-3_5_2.exe【安装步骤】
openssl
看那山瞧那水13 天前
DELPHI 利用OpenSSL实现加解密,证书(X.509)等功能
delphi·openssl
洋哥网络科技23 天前
openssl升级
openssl
Lazy Dave1 个月前
gmssl私钥文件格式
网络安全·ssl·openssl
沉在嵌入式的鱼2 个月前
RK3588移植Openssl库
linux·rk3588·openssl
黑屋里的马2 个月前
ssl相关命令生成证书
服务器·网络·ssl·openssl·gmssl
fangeqin2 个月前
ubuntu源码安装python3.13遇到Could not build the ssl module!解决方法
linux·python·ubuntu·openssl
API开发3 个月前
苹果芯片macOS安装版Homebrew(亲测) ,一键安装node、python、vscode等,比绿色软件还干净、无污染
vscode·python·docker·nodejs·openssl·brew·homebrew
码农不惑3 个月前
Rust使用tokio(二)HTTPS相关
https·rust·web·openssl
liulilittle3 个月前
通过高级处理器硬件指令集AES-NI实现AES-256-CFB算法并通过OPENSSL加密验证算法正确性。
linux·服务器·c++·算法·安全·加密·openssl