postgresql的内存分配

本文介绍了PostgreSQL中用于内存管理的MemoryContext机制。通过构建一棵由TopMemoryContext开始的树形结构来管理内存分配,避免内存泄漏。文章详细解释了核心数据结构AllocSetContext、AllocBlockData及AllocChunkData的作用及其在内存分配与回收过程中的实现。

pg为了分配内存的时候,方便管理,不产生内存泄露,引入了MemoryContext,所有的内存全从MemoryContext 中进行分配,

所有的MemoryContext构成一棵树,树的根结点为 TopMemoryContext ,TopMemoryContext 只初始化一次,在数据据库启动过程中完成初始化

每次分配是从 CurrentMemoryContext ,上面进行分配的

主要用到了三个数据结构,具体在 utils/mmgr/aset.c 的文件中

typedef struct AllocSetContext
{
MemoryContextData header; /* Standard memory-context fields */
/* Info about storage allocated in this context: */
AllocBlock blocks;    /* head of list of blocks in this set */ 是个链表
AllocChunk freelist[ALLOCSET_NUM_FREELISTS];   /* free chunk lists */ ,相同大小的构成一个纵向链表
bool   isReset;   /* T = no space alloced since last reset */
/* Allocation parameters for this context: */
Size   initBlockSize; /* initial block size */
Size   maxBlockSize; /* maximum block size */
Size   nextBlockSize; /* next block size to allocate */
Size   allocChunkLimit; /* effective chunk size limit */
AllocBlock keeper;    /* if not NULL, keep this block over resets */
} AllocSetContext;

 

ypedef struct AllocBlockData
{
AllocSet aset;    /* aset that owns this block */
AllocBlock next;    /* next block in aset's blocks list */
char    *freeptr;   /* start of free space in this block */
char    *endptr;    /* end of space in this block */
} AllocBlockData;

 

typedef struct AllocChunkData
{
/* aset is the owning aset if allocated, or the freelist link if free */
void    *aset;
/* size is always the size of the usable space in the chunk */
Size   size;
#ifdef MEMORY_CONTEXT_CHECKING
/* when debugging memory usage, also store actual requested size */
/* this is zero in a free chunk */
Size   requested_size;
#endif
} AllocChunkData

 

typedef AllocSetContext *AllocSet;

typedef struct AllocBlockData *AllocBlock;   /* forward reference */
typedef struct AllocChunkData *AllocChunk;

AllocSet   就是和MemoryContext 对应,每个 AllocSet 可以有多个 AllocBlock, 每个 AllocBlock 可以有多个 AllocChunk;AllocChunk 就是对应每次分配的内存,

AllocSet 中的所有 AllocBlock 存在 blocks 起始的链表中,释放的 AllocChunk 记录在 freelist 中,每个 freelist 是一个同样大小的 AllocChunk 链表的首接点

内存的分配和释放比较简单,就是在一大片内存中记录起始位置和大小,

### 关于C++与PostgreSQL结合使用的内存泄漏问题 在开发过程中,当涉及到C++与PostgreSQL的集成时,可能会遇到内存泄漏问题。这类问题通常源于资源管理不当或未正确释放分配的内存。以下是几种可能的解决方案和调试工具: #### 使用智能指针管理内存 为了减少手动管理内存带来的风险,可以利用现代C++中的智能指针(如`std::unique_ptr`和`std::shared_ptr`)。这些容器能够自动处理对象生命周期并确保在适当时候销毁对象[^1]。 ```cpp #include <memory> void example() { std::unique_ptr<int> ptr(new int(10)); } // 当函数结束时,ptr会自动被析构,避免了显式的delete操作。 ``` #### PostgreSQL连接池优化 如果频繁创建和关闭数据库连接,则可能导致内存消耗增加甚至泄露。通过引入连接池技术来重用已有的连接实例,从而降低每次建立新连接的成本以及潜在的风险[^2]。 ```cpp // 假设有一个全局变量存储活动连接列表 static std::vector<PGconn*> activeConnections; PGconn* getConnection(const char *conninfo){ PGconn* conn; if(!activeConnections.empty()){ conn = activeConnections.back(); activeConnections.pop_back(); }else{ conn=PQconnectdb(conninfo); } return conn; } ``` #### 调试工具推荐 对于检测复杂的程序内的内存泄漏情况,有多种强大的第三方库可供选择: - **Valgrind**: 提供详细的错误报告功能,帮助定位具体的泄漏位置; - **AddressSanitizer (ASan)**: 编译器内置插件形式存在,在运行期间捕捉非法访问行为; - **LeakSanitizer(LSAN)**: ASan的一部分专注于发现动态分配但从未释放过的区块; 以上提到的所有工具有助于快速识别哪些部分存在问题,并指导开发者修复它们。 #### 自定义日志记录机制 构建一套完善的日志体系也是预防此类隐患的有效手段之一。每当执行涉及申请/释放动作的操作时都应留下痕迹以便后续审查分析。 ```cpp #define LOG_MEMORY_ACTION(action, size) \ do { printf("%s %zu bytes at %p\n", action, size, malloc(size)); } while(false) void* my_malloc(size_t s){ void*p=malloc(s);LOG_MEMORY_ACTION("Allocated",s);return p;} void my_free(void*p){free(p);LOG_MEMORY_ACTION("Freed",(size_t)p);} ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值