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

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
* 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);
insert->left = NULL;
insert->right = NULL;
me->size++;
return insert;
}
@@ -278,7 +279,6 @@ int multiset_put(multiset me, void *const key)
return -ENOMEM;
}
me->root = insert;
me->size++;
return 0;
}
struct node *traverse = me->root;
@@ -294,7 +294,6 @@ int multiset_put(multiset me, void *const key)
}
traverse->left = insert;
multiset_insert_balance(me, insert);
me->size++;
return 0;
}
} else if (compare > 0) {
@@ -307,7 +306,6 @@ int multiset_put(multiset me, void *const key)
}
traverse->right = insert;
multiset_insert_balance(me, insert);
me->size++;
return 0;
}
} 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
* 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)
{
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;
me->buckets = calloc((size_t) me->capacity, sizeof(struct node *));
me->buckets = calloc((size_t) new_capacity, sizeof(struct node *));
if (me->buckets == NULL) {
me->buckets = old_buckets;
return -ENOMEM;
}
me->capacity = new_capacity;
for (int i = 0; i < old_capacity; i++) {
struct node *traverse = old_buckets[i];
while (traverse != NULL) {
@@ -361,6 +362,11 @@ bool unordered_map_remove(unordered_map me, void *const key)
*/
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++) {
struct node *traverse = me->buckets[i];
while (traverse != NULL) {
@@ -374,10 +380,6 @@ int unordered_map_clear(unordered_map me)
}
me->size = 0;
me->capacity = STARTING_BUCKETS;
struct node **temp = calloc((size_t) me->capacity, sizeof(struct node *));
if (temp == NULL) {
return -ENOMEM;
}
free(me->buckets);
me->buckets = temp;
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
* 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)
{
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;
me->buckets = calloc((size_t) me->capacity, sizeof(struct node *));
me->buckets = calloc((size_t) new_capacity, sizeof(struct node *));
if (me->buckets == NULL) {
me->buckets = old_buckets;
return -ENOMEM;
}
me->capacity = new_capacity;
for (int i = 0; i < old_capacity; i++) {
struct node *traverse = old_buckets[i];
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)
{
struct node **temp =
calloc((size_t) STARTING_BUCKETS, sizeof(struct node *));
if (temp == NULL) {
return -ENOMEM;
}
for (int i = 0; i < me->capacity; i++) {
struct node *traverse = me->buckets[i];
while (traverse != NULL) {
@@ -495,10 +501,6 @@ int unordered_multimap_clear(unordered_multimap me)
}
me->size = 0;
me->capacity = STARTING_BUCKETS;
struct node **temp = calloc((size_t) me->capacity, sizeof(struct node *));
if (temp == NULL) {
return -ENOMEM;
}
free(me->buckets);
me->buckets = temp;
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
* 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)
{
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;
me->buckets = calloc((size_t) me->capacity, sizeof(struct node *));
me->buckets = calloc((size_t) new_capacity, sizeof(struct node *));
if (me->buckets == NULL) {
me->buckets = old_buckets;
return -ENOMEM;
}
me->capacity = new_capacity;
for (int i = 0; i < old_capacity; i++) {
struct node *traverse = old_buckets[i];
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)
{
struct node **temp =
calloc((size_t) STARTING_BUCKETS, sizeof(struct node *));
if (temp == NULL) {
return -ENOMEM;
}
for (int i = 0; i < me->capacity; i++) {
struct node *traverse = me->buckets[i];
while (traverse != NULL) {
@@ -404,10 +410,6 @@ int unordered_multiset_clear(unordered_multiset me)
me->size = 0;
me->used = 0;
me->capacity = STARTING_BUCKETS;
struct node **temp = calloc((size_t) me->capacity, sizeof(struct node *));
if (temp == NULL) {
return -ENOMEM;
}
free(me->buckets);
me->buckets = temp;
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
* 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)
{
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;
me->buckets = calloc((size_t) me->capacity, sizeof(struct node *));
me->buckets = calloc((size_t) new_capacity, sizeof(struct node *));
if (me->buckets == NULL) {
me->buckets = old_buckets;
return -ENOMEM;
}
me->capacity = new_capacity;
for (int i = 0; i < old_capacity; i++) {
struct node *traverse = old_buckets[i];
while (traverse != NULL) {
@@ -319,6 +320,11 @@ bool unordered_set_remove(unordered_set me, void *const key)
*/
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++) {
struct node *traverse = me->buckets[i];
while (traverse != NULL) {
@@ -331,10 +337,6 @@ int unordered_set_clear(unordered_set me)
}
me->size = 0;
me->capacity = STARTING_BUCKETS;
struct node **temp = calloc((size_t) me->capacity, sizeof(struct node *));
if (temp == NULL) {
return -ENOMEM;
}
free(me->buckets);
me->buckets = temp;
return 0;

View File

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