在c++程序中使用valgrind memcheck的更直观的回溯?

x8diyxa7  于 2023-04-01  发布在  其他
关注(0)|答案(1)|浏览(117)

在调试模式下运行我的c++程序后,我获得了以下输出

valgrind --tool=memcheck --leak-check=full ./my_program

==1904766== 
==1904766== HEAP SUMMARY:
==1904766==     in use at exit: 209,434 bytes in 1,309 blocks
==1904766==   total heap usage: 871,805 allocs, 870,496 frees, 76,151,918 bytes allocated
==1904766== 
==1904766== 896 bytes in 2 blocks are possibly lost in loss record 1,289 of 1,302
==1904766==    at 0x4857A83: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==1904766==    by 0x40147D9: calloc (rtld-malloc.h:44)
==1904766==    by 0x40147D9: allocate_dtv (dl-tls.c:375)
==1904766==    by 0x40147D9: _dl_allocate_tls (dl-tls.c:634)
==1904766==    by 0x25379834: allocate_stack (allocatestack.c:430)
==1904766==    by 0x25379834: pthread_create@@GLIBC_2.34 (pthread_create.c:647)
==1904766==    by 0x2508F388: std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30)
==1904766==    by 0x14686EA2: std::thread::thread<void (std::__future_base::_Async_state_impl<std::thread::_Invoker<std::tuple<std::function<void ()> > >, void>::*)(), std::__future_base::_Async_state_impl<std::thread::_Invoker<std::tuple<std::function<void ()> > >, void>*, void>(void (std::__future_base::_Async_state_impl<std::thread::_Invoker<std::tuple<std::function<void ()> > >, void>::*&&)(), std::__future_base::_Async_state_impl<std::thread::_Invoker<std::tuple<std::function<void ()> > >, void>*&&) (std_thread.h:142)
==1904766==    by 0x14686AB4: std::__future_base::_Async_state_impl<std::thread::_Invoker<std::tuple<std::function<void ()> > >, void>::_Async_state_impl<std::function<void ()> const&>(std::function<void ()> const&) (future:1731)
==1904766==    by 0x1468660C: void std::_Construct<std::__future_base::_Async_state_impl<std::thread::_Invoker<std::tuple<std::function<void ()> > >, void>, std::function<void ()> const&>(std::__future_base::_Async_state_impl<std::thread::_Invoker<std::tuple<std::function<void ()> > >, void>*, std::function<void ()> const&) (stl_construct.h:119)
==1904766==    by 0x1468627F: void std::allocator_traits<std::allocator<void> >::construct<std::__future_base::_Async_state_impl<std::thread::_Invoker<std::tuple<std::function<void ()> > >, void>, std::function<void ()> const&>(std::allocator<void>&, std::__future_base::_Async_state_impl<std::thread::_Invoker<std::tuple<std::function<void ()> > >, void>*, std::function<void ()> const&) (alloc_traits.h:635)
==1904766==    by 0x14685DC0: std::_Sp_counted_ptr_inplace<std::__future_base::_Async_state_impl<std::thread::_Invoker<std::tuple<std::function<void ()> > >, void>, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<std::function<void ()> const&>(std::allocator<void>, std::function<void ()> const&) (shared_ptr_base.h:604)
==1904766==    by 0x14685830: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<std::__future_base::_Async_state_impl<std::thread::_Invoker<std::tuple<std::function<void ()> > >, void>, std::allocator<void>, std::function<void ()> const&>(std::__future_base::_Async_state_impl<std::thread::_Invoker<std::tuple<std::function<void ()> > >, void>*&, std::_Sp_alloc_shared_tag<std::allocator<void> >, std::function<void ()> const&) (shared_ptr_base.h:971)
==1904766==    by 0x146853C1: std::__shared_ptr<std::__future_base::_Async_state_impl<std::thread::_Invoker<std::tuple<std::function<void ()> > >, void>, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<void>, std::function<void ()> const&>(std::_Sp_alloc_shared_tag<std::allocator<void> >, std::function<void ()> const&) (shared_ptr_base.h:1712)
==1904766==    by 0x1468439E: std::shared_ptr<std::__future_base::_Async_state_impl<std::thread::_Invoker<std::tuple<std::function<void ()> > >, void> >::shared_ptr<std::allocator<void>, std::function<void ()> const&>(std::_Sp_alloc_shared_tag<std::allocator<void> >, std::function<void ()> const&) (shared_ptr.h:464)
==1904766== 
==1904766== 1,792 bytes in 4 blocks are possibly lost in loss record 1,292 of 1,302
==1904766==    at 0x4857A83: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==1904766==    by 0x40147D9: calloc (rtld-malloc.h:44)
==1904766==    by 0x40147D9: allocate_dtv (dl-tls.c:375)
==1904766==    by 0x40147D9: _dl_allocate_tls (dl-tls.c:634)
==1904766==    by 0x25379834: allocate_stack (allocatestack.c:430)
==1904766==    by 0x25379834: pthread_create@@GLIBC_2.34 (pthread_create.c:647)
==1904766==    by 0x24DE0E1C: rml::internal::thread_monitor::launch(void* (*)(void*), void*, unsigned long) (thread_monitor.h:218)
==1904766==    by 0x24DE13D4: tbb::internal::rml::private_worker::wake_or_launch() (private_server.cpp:297)
==1904766==    by 0x24DE0AE1: tbb::internal::rml::private_server::wake_some(int) (private_server.cpp:395)
==1904766==    by 0x24DE11AE: tbb::internal::rml::private_server::propagate_chain_reaction() (private_server.cpp:157)
==1904766==    by 0x24DE042C: tbb::internal::rml::private_worker::run() (private_server.cpp:257)
==1904766==    by 0x24DE02F3: tbb::internal::rml::private_worker::thread_routine(void*) (private_server.cpp:219)
==1904766==    by 0x25378B42: start_thread (pthread_create.c:442)
==1904766==    by 0x25409BB3: clone (clone.S:100)
==1904766== 
==1904766== LEAK SUMMARY:
==1904766==    definitely lost: 0 bytes in 0 blocks
==1904766==    indirectly lost: 0 bytes in 0 blocks
==1904766==      possibly lost: 2,688 bytes in 6 blocks
==1904766==    still reachable: 206,746 bytes in 1,303 blocks
==1904766==         suppressed: 0 bytes in 0 blocks
==1904766== Reachable blocks (those to which a pointer was found) are not shown.
==1904766== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==1904766== 
==1904766== For lists of detected and suppressed errors, rerun with: -s
==1904766== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

例如,与“896 bytes in 2 blocks are possibly lost in loss record...”相关的回溯对我来说不是很有描述性。有没有一种方法可以将这个回溯链接到我代码中的函数/位置?

yizd12fk

yizd12fk1#

Valgrind无法知道什么是系统代码,什么是用户代码。
它使用几种技术来生成堆栈跟踪,并从DWARF获取文件名和行号信息。
你需要花更多的时间学习如何读取和解释堆栈跟踪--同样的事情也适用于用调试器和pstack获得的回溯。
“896 bytes in 2 blocks”你不明白吗?896 bytes在两次调用分配函数时被分配。
“possibly lost”好的,你需要阅读手册。报告涵盖的不仅仅是指向已分配内存的指针超出范围的情况。请参阅手册或article
“丢失记录”对用户来说意义不大,它只是所有泄漏的计数。
阅读callstack.“calloc”这是你的分配函数。我希望所有开发人员都知道。“rtld”和“dl-tls”你需要学习这些。它们与链接加载器有关。链接加载器是负责加载exe使用的其他共享库以及解析全局数据和函数的共享库。TLS是线程本地存储。“pthread_create”相当明显,创建新线程的函数。“tbb”是您直接或间接使用的英特尔线程构建块库。“std::“所有这些都是C++标准库中的内容,所有开发人员都应该知道。
也有一些情况下,泄漏和你的代码之间没有明显的联系,例如全局变量、文件和函数静态变量。
我从所有这些中读到的是,您有一个泄漏,这是由为新线程分配的堆栈引起的。
你能分辨出你使用的是分离线程还是可连接线程吗?如果你使用的是“分离”线程,那么像这样的泄漏可能是不可避免的,而且你不能做任何事情。如果你的线程是可连接的,你可能会错过释放资源的连接。

相关问题