don't allocate a new arena in h_bind, use the existing one
Rationale: If memory allocation fails in the inner parse and we longjump up the stack, the temporary arena will be missed and leak. NB: This change means that any allocations done by the continuation (in the form of new parsers, probably) will persist for the lifetime of the parse result. Beware of wasting too much memory this way! The bind continuation should generally keep dynamic allocations to a minimum.
This commit is contained in:
parent
e26a8ff572
commit
ca1d8df06c
1 changed files with 3 additions and 10 deletions
|
|
@ -4,7 +4,6 @@ typedef struct {
|
||||||
const HParser *p;
|
const HParser *p;
|
||||||
HContinuation k;
|
HContinuation k;
|
||||||
void *env;
|
void *env;
|
||||||
HAllocator *mm__;
|
|
||||||
} BindEnv;
|
} BindEnv;
|
||||||
|
|
||||||
// an HAllocator backed by an HArena
|
// an HAllocator backed by an HArena
|
||||||
|
|
@ -39,20 +38,15 @@ static HParseResult *parse_bind(void *be_, HParseState *state) {
|
||||||
if(!res)
|
if(!res)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// create a temporary arena allocator for the continuation
|
// create a wrapper arena allocator for the continuation
|
||||||
HArena *arena = h_new_arena(be->mm__, 0);
|
ArenaAllocator aa = {{aa_alloc, aa_realloc, aa_free}, state->arena};
|
||||||
ArenaAllocator aa = {{aa_alloc, aa_realloc, aa_free}, arena};
|
|
||||||
|
|
||||||
HParser *kx = be->k((HAllocator *)&aa, res->ast, be->env);
|
HParser *kx = be->k((HAllocator *)&aa, res->ast, be->env);
|
||||||
if(!kx) {
|
if(!kx) {
|
||||||
h_delete_arena(arena);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = h_do_parse(kx, state);
|
return h_do_parse(kx, state);
|
||||||
|
|
||||||
h_delete_arena(arena);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const HParserVtable bind_vt = {
|
static const HParserVtable bind_vt = {
|
||||||
|
|
@ -76,7 +70,6 @@ HParser *h_bind__m(HAllocator *mm__,
|
||||||
be->p = p;
|
be->p = p;
|
||||||
be->k = k;
|
be->k = k;
|
||||||
be->env = env;
|
be->env = env;
|
||||||
be->mm__ = mm__;
|
|
||||||
|
|
||||||
return h_new_parser(mm__, &bind_vt, be);
|
return h_new_parser(mm__, &bind_vt, be);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue