gpt4 book ai didi

c++ - 基于预加载器的锁跟踪工具中的神秘内存泄漏

转载 作者:行者123 更新时间:2023-12-03 07:21:59 25 4
gpt4 key购买 nike

我正在开发一个锁定跟踪工具,该工具旨在使用LD_PRELOAD附加到基于Pthreads的应用程序,但遇到了一个奇怪的问题。当测试应用程序在连接了我的跟踪器的valgrind下运行时,它报告了一些源自libpthread的pthread_cond_signal()/wait()的内存泄漏(我的工具遮盖了这些功能,以实现跟踪功能)。未连接我的工具时不会发生这些泄漏。样本泄漏报告:

==12993== 48 bytes in 1 blocks are definitely lost in loss record 1 of 6                       
==12993== at 0x483DD99: calloc (vg_replace_malloc.c:762)
==12993== by 0x48C8629: pthread_cond_wait@GLIBC_2.2.5 (old_pthread_cond_wait.c:34)
==12993== by 0x48775EF: pthread_cond_wait (pthread_trace.cpp:39)
==12993== by 0x10C060: shard_get (shard.c:68)
==12993== by 0x10BC38: resolver_thread (req_res.c:74)
==12993== by 0x487789A: inject_thread_registration(void*) (pthread_trace.cpp:85)
==12993== by 0x48C0608: start_thread (pthread_create.c:477)
==12993== by 0x49FC292: clone (clone.S:95)
我不知道为什么会这样,因为我的代码完全不与Pthreads对象进行交互,除了获取它们的地址进行记录之外。这是包装函数的代码:
int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* lk) {
// log arrival at wait
the_tracer.add_event(lktrace::event::COND_WAIT, (size_t) cond);
// run pthreads function
GET_REAL_FN(pthread_cond_wait, int, pthread_cond_t*, pthread_mutex_t*);
int e = REAL_FN(cond, lk);
if (e == 0) the_tracer.add_event(lktrace::event::COND_LEAVE, (size_t) cond);
else the_tracer.add_event(lktrace::event::COND_ERR, (size_t) cond);
return e;
}

int pthread_cond_signal(pthread_cond_t* cond) {
// log cond signal
the_tracer.add_event(lktrace::event::COND_SIGNAL, (size_t) cond);
// run pthreads function
GET_REAL_FN(pthread_cond_signal, int, pthread_cond_t*);
return REAL_FN(cond);
}

// GET_REAL_FN definition:
#define GET_REAL_FN(name, rtn, params...) \
typedef rtn (*real_fn_t)(params); \
static const real_fn_t REAL_FN = (real_fn_t) dlsym(RTLD_NEXT, #name); \
assert(REAL_FN != NULL) // semicolon absence intentional
并且,为完整起见,这是pthread_cond_signal的相关glibc代码(与pthread_cond_wait相同,除了返回函数调用之外):
int
__pthread_cond_signal_2_0 (pthread_cond_2_0_t *cond)
{
if (cond->cond == NULL)
{
pthread_cond_t *newcond;

newcond = (pthread_cond_t *) calloc (sizeof (pthread_cond_t), 1); // leak alloc'd here
if (newcond == NULL)
return ENOMEM;

if (atomic_compare_and_exchange_bool_acq (&cond->cond, newcond, NULL))
/* Somebody else just initialized the condvar. */
free (newcond);
}

return __pthread_cond_signal (cond->cond);
}
测试程序(我的工具所连接到的)在退出之前确实清理了它的condvars(并且如上所述,在没有该工具的情况下运行时没有内存泄漏)。我对此很迷惑,你们有什么主意吗?我敢肯定,这很简单,却一直盯着我,总是……

最佳答案

我敢打赌,如果您:

  • 将函数的名称更改为pthread_cond_wait以外的其他名称,例如pthread_cond_wait_my
  • 创建一个小的测试代码段,以调用_my变体,
  • 创建一个最小的共享库,该库具有pthread_cond_wait_my的虚拟实现,并将代码段与其链接(就像它将与libpthread链接一样),
  • 运行该代码段,就像以前一样,通过LD_PRELOAD引入您的跟踪库,

  • ...不会有泄漏报告,即使您的库仍然使用相同的名称做完全相同的事情:)
    如果真是这样,那么泄漏对您来说是"new"的,但实际上并不是新泄漏:这是pthreads库中的真正泄漏,通常从诊断输出中抑制泄漏。 Valgrind附带了很多对运行时库的抑制-否则会很吵。但是您的工具提供了 pthread_cond_wait符号,因此Valgrind错误地将抑制作用应用于了函数,而不是将抑制作用于函数(在运行时库中)。

    关于c++ - 基于预加载器的锁跟踪工具中的神秘内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64826188/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com