acl:使用 acl 内存池模块管理动态对象

1059 篇文章 286 订阅

C/C++ 最容易出问题的地方是内存管理,容易造成内存泄露和内存越界,这一直是 C/C++ 程序员比较头疼的事情,但 C/C++ 最大的优势也是内存管理,可以让程序员直接管理内存,从而使程序运行更为高效。acl库中的内存池管理器dbuf_guard在管理内存的效率上比系统级内存管理(malloc/free, new/delete)更为高效,同时也使得内存管理更为健壮,这可以使得C/C++程序员避免出现一些常见的内存问题。本节主要介绍了 acl 库中 dbuf_guard 类的设计特点及使用方法。

dbuf_guard 类内部封装了内存池对象类 dbuf_pool,提供了与 dbuf_pool 一样的内存分配方法,dbuf_guard 类与 dbuf_pool 类的最大区别是 dbuf_guard 类对象既可以在堆上动态分配,也可以在栈上分配,而 dbuf_pool 类对象必须在堆上动态分配,另外,dbuf_guard 类还统一管理在 dbuf_pool 内存池上所创建的所有 dbuf_obj 子类对象,在 dbuf_guard 类对象析构时,所有由其管理的 dbuf_obj 子类对象被统一析构。下面先从一个简单的例子来说明 dbuf_guard 的使用方法,例子如下:


#include <iostream>
#include "acl_cpp/lib_acl.hpp"


void test(void)
{
    // 定义一个内存池管理对象
    acl::dbuf_guard dbuf;

#define	STR	"hello world"

    // 在 dbuf 对象上动态创建一个字符串内存
    char* str = dbuf.dbuf_strdup(STR);
    printf("str: %s\r\n", str);

// sizeof(STR) 取得 STR 所包含的字符串长度 + 1
    str = (char*) dbuf.dbuf_alloc(sizeof(STR));
    memcpy(str, STR, sizeof(STR));
    printf("str: %s\r\n", str);

    // 在本函数返回前,dbuf 对象自动被销毁,同时释放其所管理的
    // 内存池以及在内存池上分配的内存
}

int main(void)
{
    test();

    return 0;
}
 

在这里插入图片描述
上面的例子展示了使用 dbuf_guard 类对象直接分配内存块的过程,可以看出,所有在 dbuf_guard 对象的内存池上动态分配的内存都会在 dbuf_guard 对象销毁时被自动释放。这只是一个简单的使用 dbuf_guard 进行内存管理的例子,那么对于 C++ 对象的内存如何进行管理呢?请看下面的的例子:

class myobj : public acl::dbuf_obj
{
public:
	myobj()
	{
		// 调用系统 API 分配动态内存
		str_ = strdup("hello world");
	}
 
	void run()
	{
		printf("str: %s\r\n", str_);
	}
 
private:
	char* str_;
 
	~myobj()
	{
		// 释放构造函数中分配的内存,否则会造成内存泄露
		free(str_);
	}
};
 
void test(void)
{
	acl::dbuf_guard dbuf;
 
	// 调用 dbuf_guard::create<T>() 模板函数创建 myobj 对象
	myobj* obj = dbuf.create<myobj>();
 
	// 调用 myobj::run 方法
	obj->run();
 
	// 本函数返回前,dbuf 对象被销毁,obj 一起被销毁
} 

该例子展示了 C++ 对象在 dbuf_guard 动态创建的过程,其中有两个要点:

(1)、由 dbuf_guard 对象统一管理的 C++ 对象必须是 dbuf_obj 的子类,这样在 dbuf_guard 类对象的析构时才可以通过调用 dbuf_obj 的析构函数来达到将 dbuf_obj 子类析构的目的(其中 dbuf_obj 的析构函数为虚函数);

(2)、创建 dbuf_obj 的子类对象时,调用 dbuf_guard 对象的模板函数 create,同时指定子类名称 myobj 来创建 myobj 对象,create 内部会自动将该对象指针加入内部数组对象集合中,从而达到统一管理的目的。

上面例子的构造函数不带参数,在 dbuf_guard::create 模板函数中允许添加 0 至 10 个参数(其实内部有 11 个 create 模板函数),如果一个构造函数需要多于 10 个参数,则说明该构造函数设计的太复杂了。下面的例子展示了构造函数带参数的类对象创建过程:

 #include <assert.h>
#include "fiber/lib_fiber.hpp"


#include <iostream>
#include "acl_cpp/lib_acl.hpp"

// 继承于 acl::dbuf_obj 类
class myobj : public acl::dbuf_obj
{
public:
    myobj(int i, int j)
    {
        printf("myobj, i=%d, j=%d\r\n", i, j);
        // 在内存池上分配动态内存
        str_ = dbuf_.dbuf_strdup("hello world");
    }

    void run()
    {
        printf("str: %s\r\n", str_);
    }

private:
    char* str_;
    acl::dbuf_guard dbuf_;
    ~myobj()
    {
        // 因为 str_ 的内存也是创建在内存池上,所以此处禁止再调用 free 来释放该内存
        // free(str_);
    }
};

void test()
{
    acl::dbuf_guard dbuf;

    // 调用 dbuf_guard::create<T>(P1, P2) 模板函数创建构造函数带两个参数的 myobj 对象
    myobj* obj = dbuf.create<myobj>(10, 100);

    // 调用 myobj::run 方法
    obj->run();

    // 本函数返回前,dbuf 对象被销毁,obj 一起被销毁
}
int main(void)
{
    test();

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值