前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >日更系列:谷歌pb结构mutable滥用导致的潜在内存泄漏

日更系列:谷歌pb结构mutable滥用导致的潜在内存泄漏

原创
作者头像
mariolu
发布2022-01-29 18:22:14
1.8K0
发布2022-01-29 18:22:14
举报

算法通信协议定了一个大pb,然后往pb里面塞入各种特征。这些特征会去不同的redis表查询获取。redis查询不同表,解析返回数据,因为回调函数做成了并发异步,所以不是各个特征请求间不是串行序列化进行,所以会存在一个并发竞争问题。

对于自定义复杂对象非pld类型,protobuf (c++) 使用两种方法设置内嵌class对象的值,分别是set_allocated_ 和 mutable_。这个mutable_如果在非线程安全的环境被滥用,会有潜在的内存泄漏,这个问题比较隐蔽。

假设我们有一个例子:

message browser_user_feature
{
     feature_user_download   user_download   = 1;
     feature_query_word  query_word = 2;
}

message UserFeature {
     browser_user_feature  user_feature = 1;
}

然后用户下载数据和query数据是通过不同的redis表获取。然后我们注册回调函数去解析, 这是伪代码

register_parse_func("key1", 解析的user_download的回调函数)
register_parse_func("key2", 解析的query_word的回调函数)

解析的user_download的回调函数(data, size) {
    result.mutable_user_feature()->mutable_user_download()->ParseFromString(data, size);

}

解析的query_word的回调函数(data, size) {
    result.mutable_user_feature()->mutable_query_word()->ParseFromString(data, size);
}

那么mutable这个方面内部会进行是否空指针判断,如果是空指针,进行对象内存分配。

 inline ::feature_process::browser_user_feature* UserFeature::mutable_browser_search_user_feature() {
 
   if (browser_user_feature_ == nullptr) {
     auto* p = CreateMaybeMessage<::feature_process::browser_user_feature>(GetArenaNoVirtual());
     browser_user_feature_ = p;
   }
   // @@protoc_insertion_point(field_mutable:feature_process.UserFeature.browser_user_feature)
   return browser_user_feature_;
 }

使用内存分析工具:gperftools  https://github.com/gperftools/gperftools,会看到大量的内存分配在这个函数CreateMaybeMessage。这里注意mutable_xxx不是线程安全函数,所以分配的时候,可能会出现分配两次或多次的问题,那么后面即使释放内存也只会释放一次。

那修改这个bug的方法是什么呢?我们要保证在一个不存在线程安全问题的地方先调用一下mutable方法,预分配下内存,后续用到的时候就不会创建新内存。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 对于自定义复杂对象非pld类型,protobuf (c++) 使用两种方法设置内嵌class对象的值,分别是set_allocated_ 和 mutable_。这个mutable_如果在非线程安全的环境被滥用,会有潜在的内存泄漏,这个问题比较隐蔽。
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档