forked from RAGUL1902/Dynamic-Memory-Allocation-in-C
-
Notifications
You must be signed in to change notification settings - Fork 0
/
realloc.c
106 lines (97 loc) · 3.61 KB
/
realloc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include "include/malloc.h"
#include "include/free.h"
#include "include/realloc.h"
#include "include/metadata.h"
#include "include/memlib.h"
extern void split_space(meta_ptr block, size_t size);
extern meta_ptr merge_blocks(meta_ptr block);
extern int is_addr_valid(void *p);
extern meta_ptr get_block_addr(void *p);
/*
* This file contains the implementation of my_realloc()
* To know about meta_ptr, META_BLOCK_SIZE and other similar declarations refer the file malloc.c
* reallco() can be used to increase or decrease the size of a pre-existing memory block.
* The values in the pre-existing memory block will be copied in the new-block formed.
*/
/*
* The function copy_data() is used to copy the data from a source block to destination block.
* It runs a loop from the starting memory location till the ending memory location.
*/
void copy_data(meta_ptr src, meta_ptr dest)
{
int *src_data = (int *)src->data;
int *dest_data = (int *)dest->data;
size_t i;
for (i = 0; i * 4 < src->size && i * 4 < dest->size; i++)
{
dest_data[i] = src_data[i];
}
}
/*
* my_realloc() takes two arguments: pointer pointing to old memory location
* and the size of the new memory block to be allocated.
* If the pointer given as argument is NULL then my_malloc() is used to create a momory allocation and the new pointer is returned.
* The function first checks if the the pointer is a valid memory address,
* then if the old_block has enough memory then it is returned as it is.
* If the memory is no sufficient in the old_block then the next block is checked if its free and fused if possible.
* If the memory formed is more than requried after fusing with the next block, then the extra memory is split into a new block.
* Memory is allocated newly and the data is copied if enough memory is not found even after fusing the next free block(if available).
* Finally the pointer to the new memory address is returned.
*/
void *my_realloc(void *p, size_t size)
{
size_t s;
meta_ptr new_block, old_block;
void *new_ptr;
/* Checking if the passed pointer is NULL */
if (!p)
{
return my_malloc(size);
}
/* Checking if the passed pointer is a valid memory address or not */
if (is_addr_valid(p))
{
/* Aligning the requested size */
s = align4(size);
old_block = get_block_addr(p);
/*
* s is the new alligned space.
* old_block->size returns the size of the old memory block passes as an argument when my_realloc() is invoked
* META_BLOCK_SIZE is the size of the block storing the meta information of that memory block.
*/
if (old_block->size >= s)
{
if (old_block->size >= (META_BLOCK_SIZE + 4))
{
split_space(old_block, s);
}
}
else
{
if (old_block->next && old_block->next->free && (old_block->size + old_block->next->size + META_BLOCK_SIZE) >= s)
{
merge_blocks(old_block);
if ((intptr_t)old_block - s >= (META_BLOCK_SIZE + 4))
{
split_space(old_block, s);
}
}
else
{
new_ptr = my_malloc(s);
if (!new_ptr)
return NULL;
new_block = get_block_addr(new_ptr);
copy_data(old_block, new_block);
new_block->size = size;
my_free(p);
return new_ptr;
}
}
return p;
}
return NULL;
}