From 070c57daec076e780e81d8b1011a02ea8ac8915f Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Tue, 4 Apr 2017 21:53:44 +0300 Subject: fixes for memory leak for user-supplied sorting function. --- symbol.c | 71 ++++++++++++++++++---------------------------------------------- 1 file changed, 20 insertions(+), 51 deletions(-) (limited to 'symbol.c') diff --git a/symbol.c b/symbol.c index 65ed4d90..b2a6a6c2 100644 --- a/symbol.c +++ b/symbol.c @@ -37,7 +37,7 @@ static NODE *symbol_list; static void (*install_func)(NODE *) = NULL; static NODE *make_symbol(const char *name, NODETYPE type); static NODE *install(const char *name, NODE *parm, NODETYPE type); -static void free_bcpool(INSTRUCTION *pl); +static void free_bcpool(INSTRUCTION_POOL *pl); static AWK_CONTEXT *curr_ctxt = NULL; static int ctxt_level; @@ -693,21 +693,19 @@ check_param_names(void) return result; } -#define pool_size d.dl #define freei x.xi -static INSTRUCTION *pool_list; - -/* INSTR_CHUNK must be > largest code size (3) */ -#define INSTR_CHUNK 127 +static INSTRUCTION_POOL pools; /* bcfree --- deallocate instruction */ void bcfree(INSTRUCTION *cp) { + assert(cp->pool_size >= 1 && cp->pool_size <= MAX_INSTRUCTION_ALLOC); + cp->opcode = 0; - cp->nexti = pool_list->freei; - pool_list->freei = cp; + cp->nexti = pools.pool[cp->pool_size].freei; + pools.pool[cp->pool_size].freei = cp; } /* bcalloc --- allocate a new instruction */ @@ -717,37 +715,16 @@ bcalloc(OPCODE op, int size, int srcline) { INSTRUCTION *cp; - if (size > 1) { - /* wide instructions Op_rule, Op_func_call .. */ - emalloc(cp, INSTRUCTION *, (size + 1) * sizeof(INSTRUCTION), "bcalloc"); - cp->pool_size = size; - cp->nexti = pool_list->nexti; - pool_list->nexti = cp++; + assert(size >= 1 && size <= MAX_INSTRUCTION_ALLOC); + + if ((cp = pools.pool[size].freei) != NULL) { + pools.pool[size].freei = cp->nexti; } else { - INSTRUCTION *pool; - - pool = pool_list->freei; - if (pool == NULL) { - INSTRUCTION *last; - emalloc(cp, INSTRUCTION *, (INSTR_CHUNK + 1) * sizeof(INSTRUCTION), "bcalloc"); - - cp->pool_size = INSTR_CHUNK; - cp->nexti = pool_list->nexti; - pool_list->nexti = cp; - pool = ++cp; - last = &pool[INSTR_CHUNK - 1]; - for (; cp <= last; cp++) { - cp->opcode = 0; - cp->nexti = cp + 1; - } - --cp; - cp->nexti = NULL; - } - cp = pool; - pool_list->freei = cp->nexti; + emalloc(cp, INSTRUCTION *, (size + 1) * sizeof(INSTRUCTION), "bcalloc"); } memset(cp, 0, size * sizeof(INSTRUCTION)); + cp->pool_size = size; cp->opcode = op; cp->source_line = srcline; return cp; @@ -773,7 +750,7 @@ new_context() static void set_context(AWK_CONTEXT *ctxt) { - pool_list = & ctxt->pools; + pools = ctxt->pools; symbol_list = & ctxt->symbols; srcfiles = & ctxt->srcfiles; rule_list = & ctxt->rule_list; @@ -915,24 +892,16 @@ free_bc_internal(INSTRUCTION *cp) /* free_bcpool --- free list of instruction memory pools */ static void -free_bcpool(INSTRUCTION *pl) +free_bcpool(INSTRUCTION_POOL *pl) { - INSTRUCTION *pool, *tmp; - - for (pool = pl->nexti; pool != NULL; pool = tmp) { - INSTRUCTION *cp, *last; - long psiz; - psiz = pool->pool_size; - if (psiz == INSTR_CHUNK) - last = pool + psiz; - else - last = pool + 1; - for (cp = pool + 1; cp <= last ; cp++) { + INSTRUCTION *cp, *next; + int i; + + for (i = 1; i <= MAX_INSTRUCTION_ALLOC; i++) { + for (cp = pl->pool[i].nexti; cp != NULL; cp = next) { + next = cp->nexti; if (cp->opcode != 0) free_bc_internal(cp); } - tmp = pool->nexti; - efree(pool); } - memset(pl, 0, sizeof(INSTRUCTION)); } -- cgit v1.2.3 From 22bfbd1057c2fa9d5e5b2401d6b1ab60737452d9 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Fri, 7 Apr 2017 11:30:22 -0400 Subject: Patch INSTRUCTION allocator to malloc instruction blocks and eliminate leaks. --- symbol.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 16 deletions(-) (limited to 'symbol.c') diff --git a/symbol.c b/symbol.c index b2a6a6c2..d63277b1 100644 --- a/symbol.c +++ b/symbol.c @@ -693,8 +693,19 @@ check_param_names(void) return result; } -#define freei x.xi -static INSTRUCTION_POOL pools; +static INSTRUCTION_POOL *pools; + +/* + * For best performance, the INSTR_CHUNK value should be divisible by all + * possible sizes, i.e. 1 through MAX_INSTRUCTION_ALLOC. Otherwise, there + * will be wasted space at the end of the block. + */ +#define INSTR_CHUNK (2*3*21) + +struct instruction_block { + struct instruction_block *next; + INSTRUCTION i[INSTR_CHUNK]; +}; /* bcfree --- deallocate instruction */ @@ -704,8 +715,8 @@ bcfree(INSTRUCTION *cp) assert(cp->pool_size >= 1 && cp->pool_size <= MAX_INSTRUCTION_ALLOC); cp->opcode = 0; - cp->nexti = pools.pool[cp->pool_size].freei; - pools.pool[cp->pool_size].freei = cp; + cp->nexti = pools->pool[cp->pool_size - 1].free_list; + pools->pool[cp->pool_size - 1].free_list = cp; } /* bcalloc --- allocate a new instruction */ @@ -714,13 +725,24 @@ INSTRUCTION * bcalloc(OPCODE op, int size, int srcline) { INSTRUCTION *cp; + struct instruction_mem_pool *pool; assert(size >= 1 && size <= MAX_INSTRUCTION_ALLOC); - - if ((cp = pools.pool[size].freei) != NULL) { - pools.pool[size].freei = cp->nexti; + pool = &pools->pool[size - 1]; + + if (pool->free_list != NULL) { + cp = pool->free_list; + pool->free_list = cp->nexti; + } else if (pool->free_space && pool->free_space + size <= & pool->block_list->i[INSTR_CHUNK]) { + cp = pool->free_space; + pool->free_space += size; } else { - emalloc(cp, INSTRUCTION *, (size + 1) * sizeof(INSTRUCTION), "bcalloc"); + struct instruction_block *block; + emalloc(block, struct instruction_block *, sizeof(struct instruction_block), "bcalloc"); + block->next = pool->block_list; + pool->block_list = block; + cp = &block->i[0]; + pool->free_space = &block->i[size]; } memset(cp, 0, size * sizeof(INSTRUCTION)); @@ -750,7 +772,7 @@ new_context() static void set_context(AWK_CONTEXT *ctxt) { - pools = ctxt->pools; + pools = & ctxt->pools; symbol_list = & ctxt->symbols; srcfiles = & ctxt->srcfiles; rule_list = & ctxt->rule_list; @@ -889,19 +911,36 @@ free_bc_internal(INSTRUCTION *cp) } } -/* free_bcpool --- free list of instruction memory pools */ +/* free_bc_mempool --- free a single pool */ static void -free_bcpool(INSTRUCTION_POOL *pl) +free_bc_mempool(struct instruction_mem_pool *pool, int size) { - INSTRUCTION *cp, *next; - int i; + int first = 1; + struct instruction_block *block, *next; - for (i = 1; i <= MAX_INSTRUCTION_ALLOC; i++) { - for (cp = pl->pool[i].nexti; cp != NULL; cp = next) { - next = cp->nexti; + for (block = pool->block_list; block; block = next) { + INSTRUCTION *cp, *end; + + end = (first ? pool->free_space : & block->i[INSTR_CHUNK]); + for (cp = & block->i[0]; cp + size <= end; cp += size) { if (cp->opcode != 0) free_bc_internal(cp); } + next = block->next; + efree(block); + first = 0; } } + + +/* free_bcpool --- free list of instruction memory pools */ + +static void +free_bcpool(INSTRUCTION_POOL *pl) +{ + int i; + + for (i = 0; i < MAX_INSTRUCTION_ALLOC; i++) + free_bc_mempool(& pl->pool[i], i + 1); +} -- cgit v1.2.3 From 38bf60d89b766be81789ddd47c2e237c2af4710e Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Mon, 10 Apr 2017 15:08:32 +0300 Subject: Small style change in symbol.c. --- symbol.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'symbol.c') diff --git a/symbol.c b/symbol.c index d63277b1..51e3cf23 100644 --- a/symbol.c +++ b/symbol.c @@ -916,7 +916,7 @@ free_bc_internal(INSTRUCTION *cp) static void free_bc_mempool(struct instruction_mem_pool *pool, int size) { - int first = 1; + bool first = true; struct instruction_block *block, *next; for (block = pool->block_list; block; block = next) { @@ -929,7 +929,7 @@ free_bc_mempool(struct instruction_mem_pool *pool, int size) } next = block->next; efree(block); - first = 0; + first = false; } } -- cgit v1.2.3 From 887477763ab87b33c06df693e93500991d7c324d Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Mon, 10 Apr 2017 12:04:25 -0400 Subject: Use Op_illegal instead of 0 in a couple of places for greater clarity. --- symbol.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'symbol.c') diff --git a/symbol.c b/symbol.c index 51e3cf23..ea5ee0af 100644 --- a/symbol.c +++ b/symbol.c @@ -714,7 +714,7 @@ bcfree(INSTRUCTION *cp) { assert(cp->pool_size >= 1 && cp->pool_size <= MAX_INSTRUCTION_ALLOC); - cp->opcode = 0; + cp->opcode = Op_illegal; cp->nexti = pools->pool[cp->pool_size - 1].free_list; pools->pool[cp->pool_size - 1].free_list = cp; } @@ -924,7 +924,7 @@ free_bc_mempool(struct instruction_mem_pool *pool, int size) end = (first ? pool->free_space : & block->i[INSTR_CHUNK]); for (cp = & block->i[0]; cp + size <= end; cp += size) { - if (cp->opcode != 0) + if (cp->opcode != Op_illegal) free_bc_internal(cp); } next = block->next; -- cgit v1.2.3