繁体   English   中英

在转储libmemleak的泄漏回溯时如何显示正确的回溯?

[英]How to show correct back trace when dumping a leak backtrace by libmemleak?

我开始使用libmemleak库,并尝试使基本示例代码正常工作。

我能够捕获泄漏,但是当尝试查看回溯时,我得到了隐秘的消息。

在运行的一个终端上使用libmemleak的hello.cc示例:

LD_PRELOAD='/usr/local/lib/libmemleak.so /usr/lib/x86_64-linux-gnu/libdl.so /usr/lib/x86_64-linux-gnu/libbfd.so' ./hello

在另一个正在运行的终端上:

./memleak_control 

then 
libmemleak>start

and 
libmemleak>dump 49

泄漏示例代码(来自libmemleak存储库的hello.cc示例):

#include <iostream>
#include <cstdlib>
#include <inttypes.h>
#include <deque>
#include <cstdio>

extern "C" {
#include "addr2line.h"
}

#ifdef DIRECT_LINKED
extern "C" void memleak_stats();
extern "C" void interval_restart_recording(void);
extern "C" void interval_stop_recording(void);
#endif

void do_work(bool leak);
void* thread_entry0(void*) { do_work(false); return NULL; }
void* thread_entry1(void*) { do_work(true); return NULL; }
void* thread_entry2(void*) { do_work(false); return NULL; }
void* thread_entry3(void*) { do_work(false); return NULL; }
void purge(void);
#ifdef DIRECT_LINKED
void* monitor(void*);
int quit = 0;
#endif

size_t leaked_mem = 0;

int main()
{
  std::cout << "Entering main()" << std::endl;
#ifdef DIRECT_LINKED
  memleak_stats();
#endif

  int const threads = 4;
  pthread_t thread[threads];

  for (int i = 0; i < threads; ++i)
  {
    switch(i)
    {
      case 0:
        pthread_create(&thread[0], NULL, &thread_entry0, NULL);
        break;
      case 1:
        pthread_create(&thread[1], NULL, &thread_entry1, NULL);
        break;
      case 2:
        pthread_create(&thread[2], NULL, &thread_entry2, NULL);
        break;
      case 3:
        pthread_create(&thread[3], NULL, &thread_entry3, NULL);
        break;
    }
  }

#ifdef DIRECT_LINKED
  pthread_t monitor_thread;
  pthread_create(&monitor_thread, NULL, &monitor, NULL);
#endif

  for (int i = 0; i < threads; ++i)
    pthread_join(thread[i], NULL);

  std::cout << "All threads exited. Purging and terminating monitor thread." << std::endl;
  purge();
#ifdef DIRECT_LINKED
  quit = 1;

  pthread_join(monitor_thread, NULL);
  interval_stop_recording();
#endif

  std::cout << "Deliberate number of missed calls to free(): " << leaked_mem << std::endl;
#ifdef DIRECT_LINKED
  memleak_stats();
#endif
}

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

std::deque<void*> allocations;

void store(void* ptr)
{
  if (!ptr)
    return;
  pthread_mutex_lock(&mutex);
  allocations.push_back(ptr);
  pthread_mutex_unlock(&mutex);
}

void* remove(void)
{
  void* ret = NULL;
  pthread_mutex_lock(&mutex);
  if (!allocations.empty())
  {
    ret = allocations.front();
    allocations.pop_front();
  }
  pthread_mutex_unlock(&mutex);
  return ret;
}

void purge(void)
{
  int count = 0;
  pthread_mutex_lock(&mutex);
  while (!allocations.empty())
  {
    free(allocations.front());
    allocations.pop_front();
    ++count;
  }
  pthread_mutex_unlock(&mutex);
  std::cout << "Purged " << count << " allocations." << std::endl;
}

void do_work(bool leak)
{
  struct random_data rdata;
  int32_t rvalue;
  char rstatebuf[256];

  initstate_r(0x1234aabc, rstatebuf, sizeof(rstatebuf), &rdata);

  for (int i = 0; i < 1000000000; ++i)
  {
    random_r(&rdata, &rvalue);
    rvalue >>= 8;
    bool allocate = rvalue & 1;
    int how = (rvalue >> 1) & 0x3;
    size_t size = (rvalue >> 3) & 0xff;
    bool leak_memory = leak && ((rvalue >> 19) & 0xfff) == 0;

    if (!allocate)
    {
      void* ptr = remove();
      if (!leak_memory)
      {
        free(ptr);
      }
      else if (ptr)
        ++leaked_mem;
    }
    else
    {
      if (how == 0)
        store(realloc(remove(), size));
      else if (how == 1)
        store(calloc(13, size / 13));
      else
        store(malloc(size));
    }
  }

  pthread_exit(0);
}

实际:

libmemleak> dump 49

 #0  00007f383ffa9d76  in malloc at /home/rfogel/workspace/libmemleak/src/memleak.c:1008

 #1  00005587313eaa1a  in "hello"

 #2  00005587313eaa9e  in "hello"

 #3  00007f383efa64a4  in start_thread at /build/glibc-77giwP/glibc-2.24/nptl/pthread_create.c:456

 #4  00007f383ece8d0f  in ?? at /build/glibc-77giwP/glibc-2.24/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:99

预期:

libmemleak> dump 49

 #0  00007f84b862d33b  in malloc at /home/carlo/projects/libmemleak/libmemleak-objdir/src/../../libmemleak/src/memleak.c:1008

 #1  00000000004014da  in do_work(int)

 #2  000000000040101c  in thread_entry0(void*)

 #3  00007f84b7e7070a  in start_thread

 #4  00007f84b7b9f82d  in ?? at /build/glibc-Qz8a69/glibc-2.23/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:99

我已经联系libmemleak的主要开发人员,他将相关代码固定在库代码中的addr2line.c文件中。

链接到提交: https : //github.com/CarloWood/libmemleak/commit/ec1080cef9b33515c4e2472f1418c5bb75af1d96

现在,它可以完美运行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM