diff --git a/lib/include/tree_sitter/api.h b/lib/include/tree_sitter/api.h index c7de7662..0b64e60e 100644 --- a/lib/include/tree_sitter/api.h +++ b/lib/include/tree_sitter/api.h @@ -148,10 +148,15 @@ typedef struct { /** * Switch to a new allocator. * - * Returns the old allocator. The caller needs to take care of any allocated - * memory managed by the old allocator. + * Returns true iff the switch successes. + * + * This function can only be invoked *once*, before tree-sitter has allocated + * any memory via malloc/calloc/realloc. Otherwise, memory bugs could occur + * since some memory is allocated by the old allocator, but freed by the new + * one. + * */ -TSAllocator *ts_set_allocator(TSAllocator *new_alloc); +bool ts_set_allocator(TSAllocator *new_alloc); /** * Create a new parser. diff --git a/lib/src/alloc.c b/lib/src/alloc.c index 391430f7..65c72f11 100644 --- a/lib/src/alloc.c +++ b/lib/src/alloc.c @@ -70,10 +70,15 @@ TSAllocator *ts_allocator = &ts_default_allocator; #endif // defined(TREE_SITTER_ALLOCATION_TRACKING) -TSAllocator *ts_set_allocator(TSAllocator *new_alloc) +bool ts_set_allocator(TSAllocator *new_alloc) { - TSAllocator *old = ts_allocator; - ts_allocator = new_alloc; - return old; + static bool using_default_allocator = true; + if (!using_default_allocator) { + fprintf(stderr, "tree-sitter's allocator can only be set once!"); + return false; + } + using_default_allocator = false; + ts_allocator = new_alloc; + return true; }