llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
26.83k stars 11k forks source link

clang --objc-rewriter leaks __block variables #12636

Open llvmbot opened 12 years ago

llvmbot commented 12 years ago
Bugzilla Link 12264
Version trunk
OS All
Reporter LLVM Bugzilla Contributor
CC @tkremenek

Extended Description

when a block variable goes out of scope, _Block_object_dispose(object, BLOCK_FIELD_IS_BYREF) must be called on it. the rewriter doesn't generate that, meaning that block variables leak when any capturing block has been copied around.

Since the rewriter generates c++, a simple patch is to generate a destructor for the struct __Block_byref* that is ~__Blockbyref$foo() { _Block_object_dispose(this, 8); }

This way, RAII will take care of this.

This bug is present in any version of clang that I know about.

llvmbot commented 12 years ago

And as a "proof" that it is bogus:

Run of a program doing Block_release(Block_copy(^{ i++; })) where i is a __block variable:

When built with clang -fblocks -lBlocksRuntime:

$ ltrace -l/usr/lib/libBlocksRuntime.so.0.0 ./a _Block_copy(0x7fff2ed23d98, 0x400820, 0x4009b0, 0x7fff2ed23dc8, 0x7fdecb98c320 <unfinished ...> _Block_object_assign(0x1738030, 0x7fff2ed23dc8, 8, 0x1738010, 0x401d60) = 0x1738040 <... _Block_copy resumed> ) = 0x1738010 _Block_release(0x1738010, 0x1738030, 0x1738030, 0x1738030, 0x7fdecb98ced8 <unfinished ...> _Block_object_dispose(0x1738040, 8, 0x1738018, 0x1738010, 0x7fdecb98ced8) = 0x1000001 <... _Block_release resumed> ) = 0 _Block_object_dispose(0x7fff2ed23dc8, 8, 1, 0x1738010, 0x7fdecb98ced8) = 0x1738000

Run of c++ generated code from the clang rewriter:

$ ltrace -l/usr/lib/libBlocksRuntime.so.0.0 ./a2 _Block_copy(0x7fff33878410, 0x401ec0, 0x7fff338783f0, 0x400794, 0x22000000 <unfinished ...> _Block_object_assign(0x1f52030, 0x7fff338783f0, 8, 0x1f52030, 0x401ec0) = 0x1f52040 <... _Block_copy resumed> ) = 0x1f52010 _Block_release(0x1f52010, 0x1f52030, 0x1f52030, 0x1f52030, 0x7f5eaf656ed8 <unfinished ...> _Block_object_dispose(0x1f52040, 8, 0x1f52018, 0x1f52010, 0x7f5eaf656ed8) = 0x1000001 <... _Block_release resumed> ) = 0 +++ exited (status 0) +++

And rightfully valgrind complains:

valgrind ./a2 ==30673== Memcheck, a memory error detector ==30673== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al. ==30673== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info ==30673== Command: ./a2 ==30673== ==30673== ==30673== HEAP SUMMARY: ==30673== in use at exit: 32 bytes in 1 blocks ==30673== total heap usage: 2 allocs, 1 frees, 72 bytes allocated ==30673== ==30673== 32 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==30673== at 0x402894D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==30673== by 0x4A241FC: ??? (in /usr/lib/libBlocksRuntime.so.0.0) ==30673== by 0x4A235EA: ??? (in /usr/lib/libBlocksRuntime.so.0.0) ==30673== by 0x4A234DA: _Block_object_assign (in /usr/lib/libBlocksRuntime.so.0.0) ==30673== by 0x4007EA: main_block_copy_0(__main_block_impl_0*, main_block_impl_0*) (in /home/madcoder/a2) ==30673== by 0x4A23102: ??? (in /usr/lib/libBlocksRuntime.so.0.0) ==30673== by 0x4A22F22: _Block_copy (in /usr/lib/libBlocksRuntime.so.0.0) ==30673== by 0x400885: main (in /home/madcoder/a2) ==30673== ==30673== LEAK SUMMARY: ==30673== definitely lost: 32 bytes in 1 blocks ==30673== indirectly lost: 0 bytes in 0 blocks ==30673== possibly lost: 0 bytes in 0 blocks ==30673== still reachable: 0 bytes in 0 blocks ==30673== suppressed: 0 bytes in 0 blocks ==30673== ==30673== For counts of detected and suppressed errors, rerun with: -v ==30673== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4) valgrind ./a2 2.10s user 0.08s system 99% cpu 2.194 total

llvmbot commented 1 year ago

@llvm/issue-subscribers-clang-frontend