专栏首页分布式系统进阶记一次使用Zookeeper C API导致的内存泄漏

记一次使用Zookeeper C API导致的内存泄漏

现象
  • 线上 nginx + php-fpm来实时处理请求, php处理请求时需加载我们写的扩展;
  • 发现每次请求处理完都有少量的内存泄漏, 因为是线上实时服务, 长时间运行的话此内存泄漏不可忽视;
使用 valgrind 排查
  • 执行命令: valgrind --tool=memcheck --leak-check=full --log-file=./v.log php test.php, 其中test.php模拟线上单次请求处理;
  • log分析:
==15320== 30 (24 direct, 6 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 18  
==15320==    at 0x4A04A28: calloc (vg_replace_malloc.c:467)                                        
==15320==    by 0xB571B1B: deserialize_String_vector (zookeeper.jute.c:245)                        
==15320==    by 0xB571C69: deserialize_GetChildrenResponse (zookeeper.jute.c:874)                  
==15320==    by 0xB56C3A4: zookeeper_process (zookeeper.c:1904)                                    
==15320==    by 0xB5733CE: do_io (mt_adaptor.c:439)                                                
==15320==    by 0x38CC607A50: start_thread (in /lib64/libpthread-2.12.so)                          
==15320==    by 0xC5A06FF: ???                                                                     
==15320==                                                                                          
==15320== LEAK SUMMARY:                                                                            
==15320==    definitely lost: 24 bytes in 1 blocks                                                 
==15320==    indirectly lost: 6 bytes in 3 blocks                                                  
==15320==      possibly lost: 0 bytes in 0 blocks                                                  
==15320==    still reachable: 21,762 bytes in 29 blocks                                            
==15320==         suppressed: 0 bytes in 0 blocks                                                  
==15320== Reachable blocks (those to which a pointer was found) are not shown.                     
==15320== To see them, rerun with: --leak-check=full --show-reachable=yes                          
==15320==                                                                                          
==15320== For counts of detected and suppressed errors, rerun with: -v                             
==15320== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6)     

可以看到 definitely lost: 24 bytes in 1 blocks

解决
  • 按 valgrind的log查过去, 应该是调用zk的zoo_get_children所至, 代码如下:
String_vector children;
 if (ZOK == zoo_get_children(zk_handle_,                                                                                                                                                                
                            node_path.c_str(),                                                                                                                                                                     
                            0,                                                                                                                                                                                     
                            &children)) {
}
  • 我们来看下 String_vector(在generated/zookeeper.jute.h中)的结构:
struct String_vector {
    int32_t count;
    char * *data;
};

实际上表示一个字符串数组, count:包含的字符串个数,data: 字符串数组的指针, 那么问题就很明显了,zoo_get_children中分配了data数组的内存, 又分配了data里包含的每个字符串的内存, 但没有释放;

  • 使用 deallocate_String_vector(在generated/zookeeper.jute.h中)来释放内存, 再次运行 ``valgrind --tool=memcheck --leak-check=full --log-file=./v.log php test.php`:
==13244== Memcheck, a memory error detector                                                                                                                                                                        
==13244== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.                                                                                                                                          
==13244== Using Valgrind-3.6.0 and LibVEX; rerun with -h for copyright info                                                                                                                                        
==13244== Command: php tt.php                                                                                                                                                                                      
==13244== Parent PID: 10470                                                                                                                                                                                        
==13244==                                                                                                                                                                                                          
==13244==                                                                                                                                                                                                          
==13244== HEAP SUMMARY:                                                                                                                                                                                            
==13244==     in use at exit: 21,762 bytes in 29 blocks                                                                                                                                                            
==13244==   total heap usage: 8,779 allocs, 8,750 frees, 3,134,735 bytes allocated                                                                                                                                 
==13244==                                                                                                                                                                                                          
==13244== LEAK SUMMARY:                                                                                                                                                                                            
==13244==    definitely lost: 0 bytes in 0 blocks                                                                                                                                                                  
==13244==    indirectly lost: 0 bytes in 0 blocks                                                                                                                                                                  
==13244==      possibly lost: 0 bytes in 0 blocks                                                                                                                                                                  
==13244==    still reachable: 21,762 bytes in 29 blocks                                                                                                                                                            
==13244==         suppressed: 0 bytes in 0 blocks                                                                                                                                                                  
==13244== Reachable blocks (those to which a pointer was found) are not shown.                                                                                                                                     
==13244== To see them, rerun with: --leak-check=full --show-reachable=yes                                                                                                                                          
==13244==                                                                                                                                                                                                          
==13244== For counts of detected and suppressed errors, rerun with: -v                                                                                                                                             
==13244== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6) 

问题解决~~~

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Influxdb数据写入流程

    扫帚的影子
  • Linux 启动流程 -- 按下电源后发生的那些事儿

    扫帚的影子
  • Kafka源码分析-网络层-3

    上面的id即为我们在上篇介绍的非常重要的ConnectionId; (2) connect: 使用nio的SocketChannel连接到给定的地址,并且注册...

    扫帚的影子
  • python3使用tkinter制作动画

    import time       from tkinter import* tk=Tk()                                ...

    用户2398817
  • AI,又一领域超过人类水平

    语法改错是一个大家比较陌生的领域,大致可以认为对英文进行语法改错。给定一句带有语法错误的话,AI对其进行修正得到正确的语法表示。最近微软亚洲研究...

    CodeInHand
  • Kubernetes 中 Pod 弹性伸缩详解与使用

    本文将详细讲解HPA的核心设计原理和基于Hepaster的使用方法。此功能可以能对服务的容器数量做自动伸缩,对于服务的稳定性是一个很好的提升。

    腾讯云容器服务团队
  • python 线程池(并行编程 22)

    def sum(start, end): sum = 0 for i in range(start, end + 1): sum += i return...

    用户5760343
  • 聊聊flink Table Schema的定义

    flink-table_2.11-1.7.0-sources.jar!/org/apache/flink/table/api/StreamTableEnviro...

    codecraft
  • 聊聊flink Table Schema的定义

    flink-table_2.11-1.7.0-sources.jar!/org/apache/flink/table/api/StreamTableEnviro...

    codecraft
  • 算法之二分查找(上)

    二分查找在平时的生活中也挺常用的,比如说以前玩的猜数游戏,每次都取中间数,然后得知是大了,还是小了,这个例子也就是二分查找。

    无心的梦呓

扫码关注云+社区

领取腾讯云代金券