- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Clang's address sanitizer detects a memory leak in TBB when this program is run
#include <tbb/parallel_for.h> #include <vector> #include <cmath> template <class T> void do_not_optimize_away(T&& x) { asm volatile("" : "+r"(x)); } const int N = 100'000; void f() { std::vector<double> v(N); for (int i = 0; i < N; ++i) v = std::sqrt(i); do_not_optimize_away(v.data()); } int main() { tbb::parallel_for(0, 100, [](int i) { f(); }); return 0; }
The report I get is
================================================================= ==17071==ERROR: LeakSanitizer: detected memory leaks Direct leak of 3096 byte(s) in 3 object(s) allocated from: #0 0x4cb25b in operator new[](unsigned long) /root/clang-march30_15/llvm/projects/compiler-rt/lib/asan/asan_new_delete.cc:64:37 #1 0x7f14f5649e12 in tbb::internal::task_stream<3>::initialize(unsigned int) /root/tbb/tbb44_20150728oss/build/linux_intel64_gcc_cc4.7.3_libc2.17_kernel3.10.25_debug/../../src/tbb/task_stream.h:94 #2 0x7f14f56462f3 in tbb::internal::arena::arena(tbb::internal::market&, unsigned int) /root/tbb/tbb44_20150728oss/build/linux_intel64_gcc_cc4.7.3_libc2.17_kernel3.10.25_debug/../../src/tbb/arena.cpp:185 #3 0x7f14f5646436 in tbb::internal::arena::allocate_arena(tbb::internal::market&, unsigned int) /root/tbb/tbb44_20150728oss/build/linux_intel64_gcc_cc4.7.3_libc2.17_kernel3.10.25_debug/../../src/tbb/arena.cpp:201 #4 0x7f14f5642eab in tbb::internal::market::create_arena(int, unsigned long, bool) /root/tbb/tbb44_20150728oss/build/linux_intel64_gcc_cc4.7.3_libc2.17_kernel3.10.25_debug/../../src/tbb/market.cpp:234 #5 0x7f14f56417d2 in tbb::internal::governor::init_scheduler(int, unsigned long, bool) /root/tbb/tbb44_20150728oss/build/linux_intel64_gcc_cc4.7.3_libc2.17_kernel3.10.25_debug/../../src/tbb/governor.cpp:193 #6 0x7f14f563eac7 in tbb::internal::governor::local_scheduler() /root/tbb/tbb44_20150728oss/build/linux_intel64_gcc_cc4.7.3_libc2.17_kernel3.10.25_debug/../../src/tbb/governor.h:133 #7 0x7f14f563e380 in tbb::internal::get_initial_auto_partitioner_divisor() /root/tbb/tbb44_20150728oss/build/linux_intel64_gcc_cc4.7.3_libc2.17_kernel3.10.25_debug/../../src/tbb/task.cpp:157 #8 0x4d1d11 in tbb::interface7::internal::adaptive_partition_type_base<tbb::interface7::internal::auto_partition_type>::adaptive_partition_type_base() (/home/rnburn/bugs/tbb_leak/a.out+0x4d1d11) #9 0x4d1c1f in tbb::interface7::internal::auto_partition_type::auto_partition_type(tbb::auto_partitioner const&) (/home/rnburn/bugs/tbb_leak/a.out+0x4d1c1f) #10 0x4ccdc1 in tbb::interface7::internal::start_for<tbb::blocked_range<int>, tbb::internal::parallel_for_body<main::$_0, int>, tbb::auto_partitioner const>::start_for(tbb::blocked_range<int> const&, tbb::internal::parallel_for_body<main::$_0, int> const&, tbb::auto_partitioner const&) (/home/rnburn/bugs/tbb_leak/a.out+0x4ccdc1) #11 0x4ccc18 in tbb::interface7::internal::start_for<tbb::blocked_range<int>, tbb::internal::parallel_for_body<main::$_0, int>, tbb::auto_partitioner const>::run(tbb::blocked_range<int> const&, tbb::internal::parallel_for_body<main::$_0, int> const&, tbb::auto_partitioner const&) (/home/rnburn/bugs/tbb_leak/a.out+0x4ccc18) #12 0x4cca24 in void tbb::parallel_for<tbb::blocked_range<int>, tbb::internal::parallel_for_body<main::$_0, int> >(tbb::blocked_range<int> const&, tbb::internal::parallel_for_body<main::$_0, int> const&, tbb::auto_partitioner const&) (/home/rnburn/bugs/tbb_leak/a.out+0x4cca24) #13 0x4cc7d8 in void tbb::strict_ppl::parallel_for_impl<int, main::$_0, tbb::auto_partitioner const>(int, int, int, main::$_0 const&, tbb::auto_partitioner const&) (/home/rnburn/bugs/tbb_leak/a.out+0x4cc7d8) #14 0x4cc405 in void tbb::strict_ppl::parallel_for<int, main::$_0>(int, int, main::$_0 const&) (/home/rnburn/bugs/tbb_leak/a.out+0x4cc405) #15 0x4cc291 in main (/home/rnburn/bugs/tbb_leak/a.out+0x4cc291) #16 0x7f14f474db94 in __libc_start_main (/lib64/libc.so.6+0x24b94) SUMMARY: AddressSanitizer: 3096 byte(s) leaked in 3 allocation(s).
When I compiled with
clang++ -std=c++14 -fsanitize=address -ltbb_debug main.cpp
using clang 3.6
False positives with address sanitizer should be very rare (http://clang.llvm.org/docs/AddressSanitizer.html). And I tried adding some print statements and it looks like the destructor for task_stream may not have been called.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What happens if you put an explicit "tbb::task_scheduler_init anonymous;" just before the call to parallel_for()?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
there's no reported memory leak with "tbb::task_scheduler_init anonymous;"
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
rnickb wrote:
there's no reported memory leak with "tbb::task_scheduler_init anonymous;"
That means that if you use scoped initialization, all odjects are destroyed in the end of the scope. If you use autoinitialization (without tbb::task_scheduler_init) then created objects live till the end of the program. So it looks that everything works correctly
--Vladimir
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Can't they be deleted at the end of the program so that it doesn't flag as a memory leak?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes they can. You just need to construst this object and destruct it like it is done for other C++ objects.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Why can't the library guarantee the destructors are called, irrespective of whether task_scheduler_init object is created or not so that all the allocated heap memory gets cleanly deleted?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Upon exit OS kills worker threads where destructors are located so it is impossible to call destructors in this case. if you use C++ style for creating/deleting objects then destructors are called.
If lazy (auto) initialization is used I do not see any issues with fact that lazy de-initialization is used. And de-initialization is so lazy that it is done by an operating system.:)
--Vladimir
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
task_scheduler_init has been deprecated. What is the current BKM to use TBB with ASAN?

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page