#内存注入管理
YashanDB的C驱动支持使用外部内存管理,通过相关回调函数提供管理内存上下文的方法,从而支撑内存注入。
# 接口
函数 | 说明 |
---|---|
YacMalocFunc | 内存分配回调函数 |
YacRalocFunc | 内存重新分配回调函数 |
YacMfreeFunc | 内存释放回调函数 |
# 结构
/* YACLI mem callbacks */
typedef YacPointer (*YacMalocFunc)(YacPointer ctxp, size_t size);
typedef YacPointer (*YacRalocFunc)(YacPointer ctxp, YacPointer memptr, size_t newSize);
typedef YacVoid (*YacMfreeFunc)(YacPointer ctxp, YacPointer memptr);
YacResult yacAllocEnvWithMemCb(YacHandle* env, YacPointer ctxp, YacMalocFunc malocFp, YacRalocFunc ralocFp, YacMfreeFunc mfreeFp);
相关参数如下表所示。
参数名 | 说明 |
---|---|
env | 环境句柄 |
ctxp | 上下文指针 |
malocFp | 内存分配回调函数 |
ralocFp | 内存重新分配回调函数 |
mfreeFp | 内存释放回调函数 |
# 使用示例
# 示例一
static YacPointer testYacMalocFunc(YacPointer ctxp, size_t size)
{
YacUint32* memCtx = (YacUint32*)ctxp;
COD_ASSERT(*memCtx == 1);// 确保传递的内存上下文值为1,进行断言检查
YacPointer buf = malloc(size);
return buf;
}// 定义一个测试内存分配函数,用于在测试中替代标准库的malloc函数
static YacPointer testYacRalocFunc(YacPointer ctxp, YacPointer memptr, size_t newSize)
{
YacUint32* memCtx = (YacUint32*)ctxp;
COD_ASSERT(*memCtx == 1);
YacPointer buf = realloc(memptr, newSize);
return buf;
}// 定义一个测试内存重新分配函数,用于在测试中替代标准库的realloc函数
static YacVoid testYacMfreeFunc(YacPointer ctxp, YacPointer memptr)
{
YacUint32* memCtx = (YacUint32*)ctxp;
COD_ASSERT(*memCtx == 1);
free(memptr);
}// 定义一个测试内存释放函数,用于在测试中替代标准库的free函数
TEST_F(TestYacDriverBase, testYacMemCallback)
{
YacUint32 memCtx = 1;// 创建一个内存上下文值,用于上下文检查
YacHandle env = NULL;
YacHandle conn = NULL;
YacHandle stmt = NULL;
YAC_EXPECT_CALL(yacAllocEnvWithMemCb(&env, &memCtx, testYacMalocFunc, testYacRalocFunc, testYacMfreeFunc));// 使用内存回调环境分配函数分配环境并传递内存上下文和相关内存回调函数
YAC_EXPECT_CALL(yacAllocHandle(YAC_HANDLE_DBC, env, &conn));// 分配conn
YAC_EXPECT_CALL(yacConnect(conn, gSrvStr, YAC_NULL_TERM_STR, user, YAC_NULL_TERM_STR, pwd, YAC_NULL_TERM_STR));// 连接到数据库服务器
YAC_EXPECT_CALL(yacAllocHandle(YAC_HANDLE_STMT, conn, &stmt));// 分配stmt
YAC_EXPECT_CALL(yacDirectExecute(stmt, "select 1 from dual", YAC_NULL_TERM_STR));// 执行数据库语句
YAC_EXPECT_CALL(yacFreeHandle(YAC_HANDLE_STMT, stmt));
yacDisconnect(conn);
YAC_EXPECT_CALL(yacFreeHandle(YAC_HANDLE_DBC, conn));
YAC_EXPECT_CALL(yacFreeHandle(YAC_HANDLE_ENV, env));
}// 释放stmt,conn,env
# 示例二
typedef struct StMemCb {
YacChar* buf;// 缓冲区,用于内存分配和释放
YacUint32 bufSize;// 缓冲区总大小
YacUint32 offset;// 当前偏移量,用于跟踪已分配的内存大小
} MemCb;// 定义一个内存回调结构体 MemCb
static YacPointer testYacMalocFunc2(YacPointer ctxp, size_t size)
{
MemCb* memCtx = (MemCb*)ctxp;
if (size > memCtx->bufSize - memCtx->offset) {
return NULL;// 检查是否有足够的空间分配所需大小的内存
}
YacPointer buf = memCtx->buf + memCtx->offset;
memCtx->offset += size;
return buf;
}// 定义一个测试内存分配函数,用于在测试中替代标准库的malloc函数
static YacPointer testYacRalocFunc2(YacPointer ctxp, YacPointer memptr, size_t newSize)
{
MemCb* memCtx = (MemCb*)ctxp;
if (newSize < memCtx->bufSize - memCtx->offset) {
return NULL;
}// 检查是否有足够的空间分配所需大小的内存
YacPointer buf = memCtx->buf + memCtx->offset;
memCtx->offset += newSize;
return buf;
}// 定义一个测试内存重新分配函数,用于在测试中替代标准库的realloc函数
static YacVoid testYacMfreeFunc2(YacPointer ctxp, YacPointer memptr)
{
return;// 在这个示例中,仅用于测试,不执行实际的内存释放操作
}// 定义一个测试内存释放函数,用于在测试中替代标准库的free函数
TEST_F(TestYacDriverBase, testYacMemCallback2)// 测试使用自定义内存回调函数的情况
{
MemCb memCb;
memCb.buf = (YacChar*)malloc(10 << 20);// 分配10MB的内存缓冲区
COD_ASSERT(memCb.buf != NULL);// 检查内存分配是否成功
memCb.bufSize = 10 << 20;// 设置缓冲区总大小
memCb.offset = 0; // 初始化偏移量为0
YacHandle env = NULL;
YacHandle conn = NULL;
YacHandle stmt = NULL;
YAC_EXPECT_CALL(yacAllocEnvWithMemCb(&env, &memCb, testYacMalocFunc2, testYacRalocFunc2, testYacMfreeFunc2));
YAC_EXPECT_CALL(yacAllocHandle(YAC_HANDLE_DBC, env, &conn));
YAC_EXPECT_CALL(yacConnect(conn, gSrvStr, YAC_NULL_TERM_STR, user, YAC_NULL_TERM_STR, pwd, YAC_NULL_TERM_STR));
YAC_EXPECT_CALL(yacAllocHandle(YAC_HANDLE_STMT, conn, &stmt));
YAC_EXPECT_CALL(yacDirectExecute(stmt, "select 1 from dual", YAC_NULL_TERM_STR));
YAC_EXPECT_CALL(yacFreeHandle(YAC_HANDLE_STMT, stmt));
yacDisconnect(conn);
YAC_EXPECT_CALL(yacFreeHandle(YAC_HANDLE_DBC, conn));
YAC_EXPECT_CALL(yacFreeHandle(YAC_HANDLE_ENV, env));// 同示例一
free(memCb.buf);// 释放分配的内存缓冲区
}