内存泄露问题分析2

目前遇到线上内存泄露

  • valgrind 不能用 使用smaps gdb dump  内存后使用string 来分析,目前没有看到结果
  • 使用ltrace 跟踪malloc mmap 等?还是使用systemtap中跟踪 user-process 

继续分析一下 :

目前arm 版本 systemtap utrace 貌似不支持;ltrace 只能看到 malloc free 调用,但是看不到调用函数站,不是非常友好

找一下BCC工具链看有没有现成的,按照以前的理解,BCC工具也是基于kprobe吧

可以先看下systemp的官方例程中关于malloc的使用跟踪

#! /usr/bin/env stap

# http://developerblog.redhat.com/2015/01/06/malloc-systemtap-probes-an-example/


global sbrk, waits, arenalist, mmap_threshold = 131072, heaplist
  
  
# sbrk accounting
  
probe process("/lib*/libc.so.6").mark("memory_sbrk_more")
{
  sbrk += $arg2
}
  
probe process("/lib*/libc.so.6").mark("memory_sbrk_less")
{
  sbrk -= $arg2
}


# threshold tracking

probe process("/lib*/libc.so.6").mark("memory_mallopt_free_dyn_thresholds")
{
  printf("%d: New thresholds: mmap: %ld bytes, trim: %ld bytes
", tid(), $arg1,
         $arg2)
  mmap_threshold = $arg1
}


# arena accounting

probe process("/lib*/libc.so.6").mark("memory_arena_new")
{
  printf ("%d: Created new arena
", tid())
  arenalist[$arg1, tid()] = 1
}

probe process("/usr/lib*/libc.so.6").mark("memory_arena_reuse_wait")
{
  waits[tid()]++
}

probe process("/usr/lib*/libc.so.6").mark("memory_arena_reuse")
{
  if ($arg2 != 0)
    {
      printf ("%d: failed to allocate on own arena, trying another
", tid())
      arenalist[$arg1, tid()] = 1
    }
}

probe process("/usr/lib*/libc.so.6").mark("memory_arena_reuse_free_list")
{
  arenalist[$arg1, tid()] = 1
}

probe process.thread.end
{
  /* Find the thread and mark its arena as unused.  */
  %( systemtap_v >= "2.6"
  %?
    delete arenalist[*, tid()]
  %:
    foreach ([a, t] in arenalist)
      if (t == tid())
        break
    delete arenalist[a, t]
  %)
}


# heap accounting

probe process("/usr/lib*/libc.so.6").mark("memory_heap_new")
{
  printf("%d: New heap
", tid());
  heaplist[$arg1] = $arg2
}

probe process("/usr/lib*/libc.so.6").mark("memory_heap_more")
{
  heaplist[$arg1] = $arg2
}

probe process("/usr/lib*/libc.so.6").mark("memory_heap_less")
{
  heaplist[$arg1] = $arg2
}

probe process("/usr/lib*/libc.so.6").mark("memory_heap_free")
{
  delete heaplist[$arg1]
}


# reporting

probe begin
{
  if (target() == 0) error ("please specify target process with -c / -x")
}

probe end
{
  printf ("malloc information for pid %d
", target())
  printf ("Contention: 
")
  foreach (t in waits)
  printf ("	%d: %d waits
", t, waits[t])
  
  print("Active arenas:
")
  foreach ([a, t] in arenalist)
  {
    if (arenalist[a, t])
      printf ("	%d -> %p
", t, a)
  }
  
  print ("Allocated heaps:
")
  foreach (h in heaplist)
  {
    if (heaplist[h])
      printf ("	%p -> %ld bytes
", h, heaplist[h])
  }
  
  printf ("Total sbrk: %ld bytes
", sbrk)
  printf ("Mmap threshold in the end: %ld kb
", mmap_threshold / 1024)
}
View Code

以上代码就不详细分析了

目前需求是使用一个map记录malloc当前的堆栈,key-->val分别为地址---->堆栈 free的时候,从map中去掉,如果两次free 就会发现map 中没有此数据,此时认为重复释放

为了便于分析:从arm 平台转为x86吧

#! /usr/bin/env stap
global memaddr_tbl

global memaddr_bt_tbl

process("/lib64/libc.so.6").function("__libc_calloc").return {
    if (target() == pid()) {
        if (memaddr_tbl[$return] == 0) {
            memaddr_tbl[$return]++
            memaddr_bt_tbl[$return] = sprint_ubacktrace()
        }
    }
}

probe process("/lib64/libc.so.6").function("__libc_malloc").return {
    if (target() == pid()) {
        if (memaddr_tbl[$return] == 0) {
            memaddr_tbl[$return]++
            memaddr_bt_tbl[$return] = sprint_ubacktrace()
        }
    }
}


probe process("/lib64/libc.so.6").function("__libc_free").call {
    if (target() == pid()) {
        memaddr_tbl[$mem]--

        if (memaddr_tbl[$mem] == 0) {
          //-----------------------
        } else if (memaddr_tbl[$mem] < 0 && $mem != 0) {
            //double free  
            print_ubacktrace()
            
        }
    }
}

probe end {
    // output memleak
    printf("=============end============
")
    foreach(mem in memaddr_tbl) {
        if (memaddr_tbl[mem] > 0) {
            printf("%s
", memaddr_bt_tbl[mem])
        }
    }
}

以上例程是可以解决用户态内存泄漏点

但是 arm 平台有点不好处理! 目前虽然arm 和x86平台大部分代码一样,但是还存在部分差异,继续分析 arm差异化代码可能性

http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!! 但行好事 莫问前程 --身高体重180的胖子
原文地址:https://www.cnblogs.com/codestack/p/15071465.html