Improve failed memory allocation recovery

This commit is contained in:
Bailey Thompson
2018-01-02 12:55:08 -05:00
committed by GitHub
parent 055e2875dd
commit 2dd0b78826
7 changed files with 115 additions and 95 deletions

View File

@@ -63,8 +63,9 @@ deque deque_init(const size_t data_size)
free(init); free(init);
return NULL; return NULL;
} }
init->block->data = malloc(BLOCK_SIZE * init->data_size); struct node *const block = init->block;
if (init->block->data == NULL) { block->data = malloc(BLOCK_SIZE * init->data_size);
if (block->data == NULL) {
free(init->block); free(init->block);
free(init); free(init);
return NULL; return NULL;
@@ -111,21 +112,25 @@ int deque_trim(deque me)
{ {
const int start_block = me->start_index / BLOCK_SIZE; const int start_block = me->start_index / BLOCK_SIZE;
const int end_block = me->end_index / BLOCK_SIZE; const int end_block = me->end_index / BLOCK_SIZE;
for (int i = 0; i < start_block; i++) { const int new_block_count = end_block - start_block + 1;
free(me->block[i].data); void *const new_block = malloc(new_block_count * sizeof(struct node));
} if (new_block == NULL) {
for (int i = end_block + 1; i < me->block_count; i++) {
free(me->block[i].data);
}
me->block_count = end_block - start_block + 1;
memmove(me->block,
&me->block[start_block],
me->block_count * sizeof(struct node));
void *temp = realloc(me->block, me->block_count * sizeof(struct node));
if (temp == NULL) {
return -ENOMEM; return -ENOMEM;
} }
me->block = temp; for (int i = 0; i < start_block; i++) {
const struct node block_item = me->block[i];
free(block_item.data);
}
for (int i = end_block + 1; i < me->block_count; i++) {
const struct node block_item = me->block[i];
free(block_item.data);
}
memmove(new_block,
&me->block[start_block],
new_block_count * sizeof(struct node));
free(me->block);
me->block = new_block;
me->block_count = new_block_count;
return 0; return 0;
} }
@@ -162,14 +167,16 @@ int deque_push_front(deque me, void *const data)
if (inner_index == BLOCK_SIZE - 1) { if (inner_index == BLOCK_SIZE - 1) {
if (block_index == -1) { if (block_index == -1) {
const int old_block_count = me->block_count; const int old_block_count = me->block_count;
me->block_count = (int) ceil(RESIZE_RATIO * me->block_count); const int new_block_count =
const int added_blocks = me->block_count - old_block_count; (int) ceil(RESIZE_RATIO * me->block_count);
const int added_blocks = new_block_count - old_block_count;
void *temp = realloc(me->block, void *temp = realloc(me->block,
me->block_count * sizeof(struct node)); new_block_count * sizeof(struct node));
if (temp == NULL) { if (temp == NULL) {
return -ENOMEM; return -ENOMEM;
} }
me->block = temp; me->block = temp;
me->block_count = new_block_count;
memmove(&me->block[added_blocks], memmove(&me->block[added_blocks],
me->block, me->block,
old_block_count * sizeof(struct node)); old_block_count * sizeof(struct node));
@@ -177,19 +184,20 @@ int deque_push_front(deque me, void *const data)
me->start_index += added_blocks * BLOCK_SIZE; me->start_index += added_blocks * BLOCK_SIZE;
me->end_index += added_blocks * BLOCK_SIZE; me->end_index += added_blocks * BLOCK_SIZE;
for (int i = 0; i < added_blocks; i++) { for (int i = 0; i < added_blocks; i++) {
me->block[i].data = NULL; struct node *const block_item = &me->block[i];
block_item->data = NULL;
} }
} }
if (me->block[block_index].data == NULL) { struct node *const block_item = &me->block[block_index];
me->block[block_index].data = malloc(BLOCK_SIZE * me->data_size); if (block_item->data == NULL) {
if (me->block[block_index].data == NULL) { block_item->data = malloc(BLOCK_SIZE * me->data_size);
if (block_item->data == NULL) {
return -ENOMEM; return -ENOMEM;
} }
} }
} }
memcpy(me->block[block_index].data + inner_index * me->data_size, const struct node block_item = me->block[block_index];
data, memcpy(block_item.data + inner_index * me->data_size, data, me->data_size);
me->data_size);
me->start_index--; me->start_index--;
return 0; return 0;
} }
@@ -209,27 +217,30 @@ int deque_push_back(deque me, void *const data)
const int inner_index = me->end_index % BLOCK_SIZE; const int inner_index = me->end_index % BLOCK_SIZE;
if (inner_index == 0) { if (inner_index == 0) {
if (block_index == me->block_count) { if (block_index == me->block_count) {
me->block_count = (int) ceil(RESIZE_RATIO * me->block_count); const int new_block_count =
(int) ceil(RESIZE_RATIO * me->block_count);
void *temp = realloc(me->block, void *temp = realloc(me->block,
me->block_count * sizeof(struct node)); new_block_count * sizeof(struct node));
if (temp == NULL) { if (temp == NULL) {
return -ENOMEM; return -ENOMEM;
} }
me->block = temp; me->block = temp;
me->block_count = new_block_count;
for (int i = block_index; i < me->block_count; i++) { for (int i = block_index; i < me->block_count; i++) {
me->block[i].data = NULL; struct node *const block_item = &me->block[i];
block_item->data = NULL;
} }
} }
if (me->block[block_index].data == NULL) { struct node *const block_item = &me->block[block_index];
me->block[block_index].data = malloc(BLOCK_SIZE * me->data_size); if (block_item->data == NULL) {
if (me->block[block_index].data == NULL) { block_item->data = malloc(BLOCK_SIZE * me->data_size);
if (block_item->data == NULL) {
return -ENOMEM; return -ENOMEM;
} }
} }
} }
memcpy(me->block[block_index].data + inner_index * me->data_size, const struct node block_item = me->block[block_index];
data, memcpy(block_item.data + inner_index * me->data_size, data, me->data_size);
me->data_size);
me->end_index++; me->end_index++;
return 0; return 0;
} }
@@ -251,9 +262,8 @@ int deque_pop_front(void *const data, deque me)
me->start_index++; me->start_index++;
const int block_index = me->start_index / BLOCK_SIZE; const int block_index = me->start_index / BLOCK_SIZE;
const int inner_index = me->start_index % BLOCK_SIZE; const int inner_index = me->start_index % BLOCK_SIZE;
memcpy(data, const struct node block_item = me->block[block_index];
me->block[block_index].data + inner_index * me->data_size, memcpy(data, block_item.data + inner_index * me->data_size, me->data_size);
me->data_size);
return 0; return 0;
} }
@@ -274,9 +284,8 @@ int deque_pop_back(void *const data, deque me)
me->end_index--; me->end_index--;
const int block_index = me->end_index / BLOCK_SIZE; const int block_index = me->end_index / BLOCK_SIZE;
const int inner_index = me->end_index % BLOCK_SIZE; const int inner_index = me->end_index % BLOCK_SIZE;
memcpy(data, const struct node block_item = me->block[block_index];
me->block[block_index].data + inner_index * me->data_size, memcpy(data, block_item.data + inner_index * me->data_size, me->data_size);
me->data_size);
return 0; return 0;
} }
@@ -312,9 +321,8 @@ int deque_set_at(deque me, int index, void *const data)
index += me->start_index + 1; index += me->start_index + 1;
const int block_index = index / BLOCK_SIZE; const int block_index = index / BLOCK_SIZE;
const int inner_index = index % BLOCK_SIZE; const int inner_index = index % BLOCK_SIZE;
memcpy(me->block[block_index].data + inner_index * me->data_size, const struct node block_item = me->block[block_index];
data, memcpy(block_item.data + inner_index * me->data_size, data, me->data_size);
me->data_size);
return 0; return 0;
} }
@@ -364,9 +372,8 @@ int deque_get_at(void *const data, deque me, int index)
index += me->start_index + 1; index += me->start_index + 1;
const int block_index = index / BLOCK_SIZE; const int block_index = index / BLOCK_SIZE;
const int inner_index = index % BLOCK_SIZE; const int inner_index = index % BLOCK_SIZE;
memcpy(data, const struct node block_item = me->block[block_index];
me->block[block_index].data + inner_index * me->data_size, memcpy(data, block_item.data + inner_index * me->data_size, me->data_size);
me->data_size);
return 0; return 0;
} }
@@ -394,21 +401,26 @@ int deque_get_last(void *const data, deque me)
*/ */
int deque_clear(deque me) int deque_clear(deque me)
{ {
struct node *const temp_block = malloc(sizeof(struct node));
if (temp_block == NULL) {
return -ENOMEM;
}
void *const temp_block_data = malloc(BLOCK_SIZE * me->data_size);
if (temp_block_data == NULL) {
free(temp_block);
return -ENOMEM;
}
for (int i = 0; i < me->block_count; i++) { for (int i = 0; i < me->block_count; i++) {
free(me->block[i].data); const struct node block_item = me->block[i];
free(block_item.data);
} }
free(me->block); free(me->block);
me->start_index = BLOCK_SIZE / 2; me->start_index = BLOCK_SIZE / 2;
me->end_index = me->start_index + 1; me->end_index = me->start_index + 1;
me->block_count = 1; me->block_count = 1;
me->block = malloc(sizeof(struct node)); me->block = temp_block;
if (me->block == NULL) { struct node *const block = me->block;
return -ENOMEM; block->data = temp_block_data;
}
me->block->data = malloc(BLOCK_SIZE * me->data_size);
if (me->block->data == NULL) {
return -ENOMEM;
}
return 0; return 0;
} }
@@ -422,7 +434,8 @@ int deque_clear(deque me)
deque deque_destroy(deque me) deque deque_destroy(deque me)
{ {
for (int i = 0; i < me->block_count; i++) { for (int i = 0; i < me->block_count; i++) {
free(me->block[i].data); const struct node block_item = me->block[i];
free(block_item.data);
} }
free(me->block); free(me->block);
free(me); free(me);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017 Bailey Thompson * Copyright (c) 2017-2018 Bailey Thompson
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@@ -258,6 +258,7 @@ static struct node *multiset_create_node(multiset me,
memcpy(insert->key, data, me->key_size); memcpy(insert->key, data, me->key_size);
insert->left = NULL; insert->left = NULL;
insert->right = NULL; insert->right = NULL;
me->size++;
return insert; return insert;
} }
@@ -278,7 +279,6 @@ int multiset_put(multiset me, void *const key)
return -ENOMEM; return -ENOMEM;
} }
me->root = insert; me->root = insert;
me->size++;
return 0; return 0;
} }
struct node *traverse = me->root; struct node *traverse = me->root;
@@ -294,7 +294,6 @@ int multiset_put(multiset me, void *const key)
} }
traverse->left = insert; traverse->left = insert;
multiset_insert_balance(me, insert); multiset_insert_balance(me, insert);
me->size++;
return 0; return 0;
} }
} else if (compare > 0) { } else if (compare > 0) {
@@ -307,7 +306,6 @@ int multiset_put(multiset me, void *const key)
} }
traverse->right = insert; traverse->right = insert;
multiset_insert_balance(me, insert); multiset_insert_balance(me, insert);
me->size++;
return 0; return 0;
} }
} else { } else {

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017 Bailey Thompson * Copyright (c) 2017-2018 Bailey Thompson
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@@ -160,13 +160,14 @@ bool unordered_map_is_empty(unordered_map me)
static int unordered_map_resize(unordered_map me) static int unordered_map_resize(unordered_map me)
{ {
const int old_capacity = me->capacity; const int old_capacity = me->capacity;
me->capacity *= RESIZE_RATIO; const int new_capacity = (int) (me->capacity * RESIZE_RATIO);
struct node **old_buckets = me->buckets; struct node **old_buckets = me->buckets;
me->buckets = calloc((size_t) me->capacity, sizeof(struct node *)); me->buckets = calloc((size_t) new_capacity, sizeof(struct node *));
if (me->buckets == NULL) { if (me->buckets == NULL) {
me->buckets = old_buckets; me->buckets = old_buckets;
return -ENOMEM; return -ENOMEM;
} }
me->capacity = new_capacity;
for (int i = 0; i < old_capacity; i++) { for (int i = 0; i < old_capacity; i++) {
struct node *traverse = old_buckets[i]; struct node *traverse = old_buckets[i];
while (traverse != NULL) { while (traverse != NULL) {
@@ -361,6 +362,11 @@ bool unordered_map_remove(unordered_map me, void *const key)
*/ */
int unordered_map_clear(unordered_map me) int unordered_map_clear(unordered_map me)
{ {
struct node **temp =
calloc((size_t) STARTING_BUCKETS, sizeof(struct node *));
if (temp == NULL) {
return -ENOMEM;
}
for (int i = 0; i < me->capacity; i++) { for (int i = 0; i < me->capacity; i++) {
struct node *traverse = me->buckets[i]; struct node *traverse = me->buckets[i];
while (traverse != NULL) { while (traverse != NULL) {
@@ -374,10 +380,6 @@ int unordered_map_clear(unordered_map me)
} }
me->size = 0; me->size = 0;
me->capacity = STARTING_BUCKETS; me->capacity = STARTING_BUCKETS;
struct node **temp = calloc((size_t) me->capacity, sizeof(struct node *));
if (temp == NULL) {
return -ENOMEM;
}
free(me->buckets); free(me->buckets);
me->buckets = temp; me->buckets = temp;
return 0; return 0;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017 Bailey Thompson * Copyright (c) 2017-2018 Bailey Thompson
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@@ -179,13 +179,14 @@ bool unordered_multimap_is_empty(unordered_multimap me)
static int unordered_multimap_resize(unordered_multimap me) static int unordered_multimap_resize(unordered_multimap me)
{ {
const int old_capacity = me->capacity; const int old_capacity = me->capacity;
me->capacity *= RESIZE_RATIO; const int new_capacity = (int) (me->capacity * RESIZE_RATIO);
struct node **old_buckets = me->buckets; struct node **old_buckets = me->buckets;
me->buckets = calloc((size_t) me->capacity, sizeof(struct node *)); me->buckets = calloc((size_t) new_capacity, sizeof(struct node *));
if (me->buckets == NULL) { if (me->buckets == NULL) {
me->buckets = old_buckets; me->buckets = old_buckets;
return -ENOMEM; return -ENOMEM;
} }
me->capacity = new_capacity;
for (int i = 0; i < old_capacity; i++) { for (int i = 0; i < old_capacity; i++) {
struct node *traverse = old_buckets[i]; struct node *traverse = old_buckets[i];
while (traverse != NULL) { while (traverse != NULL) {
@@ -482,6 +483,11 @@ bool unordered_multimap_remove_all(unordered_multimap me, void *const key)
*/ */
int unordered_multimap_clear(unordered_multimap me) int unordered_multimap_clear(unordered_multimap me)
{ {
struct node **temp =
calloc((size_t) STARTING_BUCKETS, sizeof(struct node *));
if (temp == NULL) {
return -ENOMEM;
}
for (int i = 0; i < me->capacity; i++) { for (int i = 0; i < me->capacity; i++) {
struct node *traverse = me->buckets[i]; struct node *traverse = me->buckets[i];
while (traverse != NULL) { while (traverse != NULL) {
@@ -495,10 +501,6 @@ int unordered_multimap_clear(unordered_multimap me)
} }
me->size = 0; me->size = 0;
me->capacity = STARTING_BUCKETS; me->capacity = STARTING_BUCKETS;
struct node **temp = calloc((size_t) me->capacity, sizeof(struct node *));
if (temp == NULL) {
return -ENOMEM;
}
free(me->buckets); free(me->buckets);
me->buckets = temp; me->buckets = temp;
return 0; return 0;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017 Bailey Thompson * Copyright (c) 2017-2018 Bailey Thompson
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@@ -160,13 +160,14 @@ bool unordered_multiset_is_empty(unordered_multiset me)
static int unordered_multiset_resize(unordered_multiset me) static int unordered_multiset_resize(unordered_multiset me)
{ {
const int old_capacity = me->capacity; const int old_capacity = me->capacity;
me->capacity *= RESIZE_RATIO; const int new_capacity = (int) (me->capacity * RESIZE_RATIO);
struct node **old_buckets = me->buckets; struct node **old_buckets = me->buckets;
me->buckets = calloc((size_t) me->capacity, sizeof(struct node *)); me->buckets = calloc((size_t) new_capacity, sizeof(struct node *));
if (me->buckets == NULL) { if (me->buckets == NULL) {
me->buckets = old_buckets; me->buckets = old_buckets;
return -ENOMEM; return -ENOMEM;
} }
me->capacity = new_capacity;
for (int i = 0; i < old_capacity; i++) { for (int i = 0; i < old_capacity; i++) {
struct node *traverse = old_buckets[i]; struct node *traverse = old_buckets[i];
while (traverse != NULL) { while (traverse != NULL) {
@@ -391,6 +392,11 @@ bool unordered_multiset_remove_all(unordered_multiset me, void *const key)
*/ */
int unordered_multiset_clear(unordered_multiset me) int unordered_multiset_clear(unordered_multiset me)
{ {
struct node **temp =
calloc((size_t) STARTING_BUCKETS, sizeof(struct node *));
if (temp == NULL) {
return -ENOMEM;
}
for (int i = 0; i < me->capacity; i++) { for (int i = 0; i < me->capacity; i++) {
struct node *traverse = me->buckets[i]; struct node *traverse = me->buckets[i];
while (traverse != NULL) { while (traverse != NULL) {
@@ -404,10 +410,6 @@ int unordered_multiset_clear(unordered_multiset me)
me->size = 0; me->size = 0;
me->used = 0; me->used = 0;
me->capacity = STARTING_BUCKETS; me->capacity = STARTING_BUCKETS;
struct node **temp = calloc((size_t) me->capacity, sizeof(struct node *));
if (temp == NULL) {
return -ENOMEM;
}
free(me->buckets); free(me->buckets);
me->buckets = temp; me->buckets = temp;
return 0; return 0;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017 Bailey Thompson * Copyright (c) 2017-2018 Bailey Thompson
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@@ -155,13 +155,14 @@ bool unordered_set_is_empty(unordered_set me)
static int unordered_set_resize(unordered_set me) static int unordered_set_resize(unordered_set me)
{ {
const int old_capacity = me->capacity; const int old_capacity = me->capacity;
me->capacity *= RESIZE_RATIO; const int new_capacity = (int) (me->capacity * RESIZE_RATIO);
struct node **old_buckets = me->buckets; struct node **old_buckets = me->buckets;
me->buckets = calloc((size_t) me->capacity, sizeof(struct node *)); me->buckets = calloc((size_t) new_capacity, sizeof(struct node *));
if (me->buckets == NULL) { if (me->buckets == NULL) {
me->buckets = old_buckets; me->buckets = old_buckets;
return -ENOMEM; return -ENOMEM;
} }
me->capacity = new_capacity;
for (int i = 0; i < old_capacity; i++) { for (int i = 0; i < old_capacity; i++) {
struct node *traverse = old_buckets[i]; struct node *traverse = old_buckets[i];
while (traverse != NULL) { while (traverse != NULL) {
@@ -319,6 +320,11 @@ bool unordered_set_remove(unordered_set me, void *const key)
*/ */
int unordered_set_clear(unordered_set me) int unordered_set_clear(unordered_set me)
{ {
struct node **temp =
calloc((size_t) STARTING_BUCKETS, sizeof(struct node *));
if (temp == NULL) {
return -ENOMEM;
}
for (int i = 0; i < me->capacity; i++) { for (int i = 0; i < me->capacity; i++) {
struct node *traverse = me->buckets[i]; struct node *traverse = me->buckets[i];
while (traverse != NULL) { while (traverse != NULL) {
@@ -331,10 +337,6 @@ int unordered_set_clear(unordered_set me)
} }
me->size = 0; me->size = 0;
me->capacity = STARTING_BUCKETS; me->capacity = STARTING_BUCKETS;
struct node **temp = calloc((size_t) me->capacity, sizeof(struct node *));
if (temp == NULL) {
return -ENOMEM;
}
free(me->buckets); free(me->buckets);
me->buckets = temp; me->buckets = temp;
return 0; return 0;

View File

@@ -88,15 +88,15 @@ bool vector_is_empty(vector me)
*/ */
static int vector_set_space(vector me, const int size) static int vector_set_space(vector me, const int size)
{ {
me->space = size; void *const temp = realloc(me->storage, size * me->data_size);
if (me->space < me->offset) {
me->offset = me->space;
}
void *const temp = realloc(me->storage, me->space * me->data_size);
if (temp == NULL) { if (temp == NULL) {
return -ENOMEM; return -ENOMEM;
} }
me->storage = temp; me->storage = temp;
me->space = size;
if (me->space < me->offset) {
me->offset = me->space;
}
return 0; return 0;
} }
@@ -188,12 +188,13 @@ int vector_add_at(vector me, const int index, void *const data)
return -EINVAL; return -EINVAL;
} }
if (me->offset + 1 >= me->space) { if (me->offset + 1 >= me->space) {
me->space *= RESIZE_RATIO; const int new_space = (int) (me->space * RESIZE_RATIO);
void *const temp = realloc(me->storage, me->space * me->data_size); void *const temp = realloc(me->storage, new_space * me->data_size);
if (temp == NULL) { if (temp == NULL) {
return -ENOMEM; return -ENOMEM;
} }
me->storage = temp; me->storage = temp;
me->space = new_space;
} }
if (index != me->offset) { if (index != me->offset) {
memmove(me->storage + (index + 1) * me->data_size, memmove(me->storage + (index + 1) * me->data_size,