解决protobuf内存泄漏的3种办法

本文探讨了protobuf对象的内存释放机制,指出protobuf的Clear()方法并不释放堆内存,而应该借助智能指针如shared_ptr的reset()接口来实现内存的真正释放。通过示例展示了protobuf对象作为成员变量时,如何利用shared_ptr进行内存管理,以避免内存泄漏。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.protobuf对象是如何释放(数组)内存的?

        毫无疑问是,通过调用析构函数。只要让protobuf定义的对象调用析构函数,无论嵌套了多少层数据、包含了多少个数组都可以释放new出来的内存。

2.protobuf对象Clear()接口和STL容器中的clear()接口的有何区别?

        我们习惯使用STL模板中各类容器(vector,map,set),而不用考虑底层对内存的使用。无论装在容器中的数据如何复杂如何庞大,只要能执行clear()就可以一了百了。

        但是,相同情况用到protobuf却不尽然。protobuf对象的Clear()操作,只是反复调用memset执行内存重置为0的操作,这就好比将电脑C盘格式化,但C盘的容量并没有改变。

3.protobuf对象作为成员变量,如何释放内存?

        考虑一种情况:protobuf对象作为成员变量,一直存在内存使用(增删改),也需要对它进行周期性清空操作(调用Clear()接口实现内存重置为0)。如何在清空操作的同时释放所占用的内存的空间?

        答:借助共享指针shared_ptr的reset()接口。

举例说明:

protobuf协议定义如下,ConfigItem里面包含一个SubItem数组,在测试例子中调用ConfigItem中add_items() 填充1000条数据。
 

package proto;

message SubItem
{
	required int32 id = 1;
	required int32 type = 2;
	required int32 value = 3;
}

message ConfigItem
{
	repeated SubItem items = 1;
}

测试C++代码:

#include<memory>
#include"client.pb.h"

using std::shared_ptr;

void readCfg_verson1()
{
	proto::ConfigItem config;
	for ( int idx = 0; idx < 1000; idx++ )
	{
		auto item = config.add_items();
		item->set_id(idx);
		item->set_type(idx);
		item->set_value(idx);
	}
}

void readCfg_version2()
{
	proto::ConfigItem *pconfig = new proto::ConfigItem;
	for ( int idx = 0; idx < 1000; idx++ )
	{
		auto item = pconfig->add_items();
		item->set_id(idx);
		item->set_type(idx);
		item->set_value(idx);
	}
	delete pconfig;
}

class Foo
{
public:

	Foo():pconfig_(new proto::ConfigItem){}

	shared_ptr<proto::ConfigItem> pconfig_;

	void readCfg_version3()
	{
		for ( int idx = 0; idx < 1000; idx++ )
		{
			auto item = pconfig_->add_items();
			item->set_id(idx);
			item->set_type(idx);
			item->set_value(idx);
		}
	}
};

int main(void)
{
	//1.protobuf对象作为栈对象自动析构
	readCfg_verson1();

	//2.protobuf对象堆对象使用delete手动析构
	readCfg_version2();

	//3.protobuf对象作为成员变量借用shared_ptr的reset()接口调用析构函数
	Foo foo;
	foo.readCfg_version3();

	//千万注意:使用protobuf自带的Clear()函数,相当于对C数组进行memset操作,跟STL容器的clear()接口作用不一样,将内存重置为0并没有释放所占用的堆内存空间。
	foo.config_->Clear();

	//正确做法://借助智能指针shared_ptr的reset()接口,析构老对象并释放所占内存,同时重新创建一个新对象(只占用一个指针的内存)。
	proom->pconfig_.reset(new proto::ConfigItem);

	//todo ...

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值