bool _check_leaks_pop(TALLOC_CTX *ctx, const char *location) { struct size_snapshot *snapshot; TALLOC_CTX *old_ctx; size_t bytes_allocated; if (ctx == NULL) { return false; } if (snapshot_stack == NULL) { _set_leak_err_msg("%s: trying to pop an empty stack", location); return false; } snapshot = snapshot_stack; DLIST_REMOVE(snapshot_stack, snapshot); old_ctx = snapshot->ctx; bytes_allocated = snapshot->bytes_allocated; if (old_ctx != ctx) { _set_leak_err_msg("Bad push/pop order"); return false; } talloc_zfree(snapshot); return _check_leaks(old_ctx, bytes_allocated, location); }
bool leak_check_teardown(void) { check_leaks_pop(global_talloc_context); if (snapshot_stack != NULL) { _set_leak_err_msg("Exiting with a non-empty stack"); return false; } return check_leaks(global_talloc_context, 0); }
bool leak_check_setup(void) { talloc_enable_null_tracking(); global_talloc_context = talloc_new(NULL); if (global_talloc_context == NULL) { _set_leak_err_msg("talloc_new failed"); return false; } check_leaks_push(global_talloc_context); return true; }
bool leak_check_teardown(void) { bool res; check_leaks_pop(global_talloc_context); if (snapshot_stack != NULL) { _set_leak_err_msg("Exiting with a non-empty stack"); return false; } res = check_leaks(global_talloc_context, 0); talloc_disable_null_tracking(); talloc_free(global_talloc_context); return res; }
bool _check_leaks(TALLOC_CTX *ctx, size_t bytes, const char *location) { size_t bytes_allocated; bytes_allocated = talloc_total_size(ctx); if (bytes_allocated != bytes) { fprintf(stderr, "Leak report for %s:\n", location); talloc_report_full(ctx, stderr); _set_leak_err_msg("%s: memory leaks detected, %zd bytes still allocated", location, bytes_allocated - bytes); return false; } return true; }