I am writing a C program that uses Apple's Blocks extension to provide lexical closures. I am also using the Boehm garbage collector. What I would like is for Block_copy() to use GC_MALLOC when allocating blocks on the heap, so that they are garbage collected.
#include <stdio.h>
#include <Block.h>
#include <GC.h>
int main()
{
int i = 42;
void(^test)(void) = Block_copy(^{printf("Hello %d\n", i);});
test();
}
I compiled libBlocksRuntime (https://github.com/mackyle/blocksruntime) from source using -DREDIRECT_MALLOC=GC_MALLOC -DREDIRECT_REALLOC=GC_REALLOC -DIGNORE_FREE
in order to have Boehm override malloc() and realloc() calls.
I then compiled the above c program with -fblocks -lBlocksRuntime -l:libgc.so -fsanitize=address
but it showed that memory was leaked and thus Boehm's allocator was unused by Block_copy().
Hello 42
==5885==WARNING: invalid path to external symbolizer!
==5885==WARNING: Failed to use and restart external symbolizer!
=================================================================
==5885==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 36 byte(s) in 1 object(s) allocated from:
#0 0x4961ed (/home/finn/test+0x4961ed)
#1 0x7ff40c7e0c04 (/lib/x86_64-linux-gnu/libBlocksRuntime.so.0+0xc04)
#2 0x7ff40c436cc9 (/lib/x86_64-linux-gnu/libc.so.6+0x26cc9)
SUMMARY: AddressSanitizer: 36 byte(s) leaked in 1 allocation(s).
How can I force libBlocksRuntime to use Boehm's memory allocator?
EDIT: I've tried to solve this by using malloc hooks, and then with LD_PRELOAD, but neither of these seem to cooperate with libBlocksRuntime (or blocks in general for that matter).
Ok, I've finally worked it out. There's probably a better way of doing this, but the only documentation for this I could find was the source code. Firstly, you need to
#include
theBlock_private.h
header as well asBlock.h
. This allows access to the_Block_use_GC()
function. The version of libBlocksRuntime in the Debian repositories is unsuitable for this, since_Block_use_GC()
was not compiled into itslibBlocksRuntime.so
. You then need to define these 5 functions:These are the functions that libBlocksRuntime is going to use to access the garbage collector. The important one in this case is
blk_alloc()
, which just callsGC_MALLOC()
. Other garbage collectors may use the other functions however, and you can probably leverage them for better performance. Now we have to tell libBlocksRuntime to use these functions like so:This informs libBlocksRuntime that we are using a garbage collector, and this is how to interface with it.