Skip to content

Commit 83aec29

Browse files
committed
arena: fix behavior when alloc_size > block_size
1 parent 3731057 commit 83aec29

File tree

1 file changed

+28
-9
lines changed

1 file changed

+28
-9
lines changed

src/common/arena.c

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Arena* new_arena() {
2424
*arena = (Arena) {
2525
.nblocks = 0,
2626
.maxblocks = 256,
27-
.blocks = malloc(256 * sizeof(size_t)),
27+
.blocks = malloc(256 * sizeof(void*)),
2828
.available = 0,
2929
};
3030
for (int i = 0; i < arena->maxblocks; i++)
@@ -40,20 +40,39 @@ void destroy_arena(Arena* arena) {
4040
free(arena);
4141
}
4242

43+
static void* new_block(Arena* arena, size_t size) {
44+
assert(arena->nblocks <= arena->maxblocks);
45+
// we need more storage for the block pointers themselves !
46+
if (arena->nblocks == arena->maxblocks) {
47+
arena->maxblocks *= 2;
48+
arena->blocks = realloc(arena->blocks, arena->maxblocks * sizeof(void*));
49+
}
50+
51+
void* allocated = malloc(size);
52+
assert(allocated);
53+
arena->blocks[arena->nblocks++] = allocated;
54+
return allocated;
55+
}
56+
4357
void* arena_alloc(Arena* arena, size_t size) {
4458
size = round_up(size, (size_t) sizeof(max_align_t));
4559
if (size == 0)
4660
return NULL;
47-
// arena is full
48-
if (size > arena->available) {
49-
assert(arena->nblocks <= arena->maxblocks);
50-
// we need more storage for the block pointers themselves !
51-
if (arena->nblocks == arena->maxblocks) {
52-
arena->maxblocks *= 2;
53-
arena->blocks = realloc(arena->blocks, arena->maxblocks);
61+
if (size > alloc_size) {
62+
void* allocated = new_block(arena, size);
63+
memset(allocated, 0, size);
64+
// swap the last two blocks
65+
if (arena->nblocks >= 2) {
66+
void* swap = arena->blocks[arena->nblocks - 1];
67+
arena->blocks[arena->nblocks - 1] = arena->blocks[arena->nblocks - 2];
68+
arena->blocks[arena->nblocks - 2] = swap;
5469
}
70+
return allocated;
71+
}
5572

56-
arena->blocks[arena->nblocks++] = malloc(alloc_size);
73+
// arena is full
74+
if (size > arena->available) {
75+
new_block(arena, alloc_size);
5776
arena->available = alloc_size;
5877
}
5978

0 commit comments

Comments
 (0)