Skip to content

Commit cad0615

Browse files
authored
Implement advanced free features (#32)
## Description Implement advanced free features ## Issues <!-- use if this PR fully resolves the issue --> Closes #30 <!-- use if this PR is linked but should not close the issue --> Related: #<issue-number> ## Testing <!-- Steps or notes on how reviewers can verify. -->
1 parent ce42efe commit cad0615

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed

include/malloc_from_scratch/memory_internal.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ void* splitFreeMemoryBlockIfPossible(MemoryBlock* new_block, size_t size);
3232
void* getMemoryBlockSplitAddress(MemoryBlock* new_block, size_t size);
3333
void insertMemoryBlockAtEnd(MemoryBlock** block_list_head, MemoryBlock* new_block);
3434

35+
// free
36+
void decreaseHeap(MemoryBlock* block_heap_end);
37+
void mergeFreeMemoryBlocks();
38+
void getLastMemoryBlock(MemoryBlock** block_list_tail, MemoryBlock** block_previous_from_last);
39+
3540
// helpers
3641
void* getPayloadAddress(MemoryBlock* block);
3742
MemoryBlock* getMetadata(void* payload_address);

src/free.cpp

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
#include "malloc_from_scratch/memory_allocator.h"
2+
#include "malloc_from_scratch/memory_internal.h"
3+
4+
#include <cstdlib>
5+
#include <unistd.h>
26

37
namespace mem
48
{
@@ -9,6 +13,97 @@ void free(void* ptr)
913
{
1014
return;
1115
}
16+
17+
void* current_program_break = sbrk(0);
18+
19+
if (ptr < internal::heap_start || ptr >= current_program_break)
20+
{
21+
return;
22+
}
23+
24+
internal::MemoryBlock* block_to_free = internal::getMetadata(ptr);
25+
if (block_to_free == nullptr || block_to_free->allocated_ == false)
26+
{
27+
return;
28+
}
29+
block_to_free->allocated_ = false;
30+
31+
internal::mergeFreeMemoryBlocks();
32+
33+
internal::MemoryBlock* block_list_tail = nullptr;
34+
internal::MemoryBlock* block_previous_from_last = nullptr;
35+
36+
internal::getLastMemoryBlock(&block_list_tail, &block_previous_from_last);
37+
if (block_list_tail != nullptr && block_list_tail->allocated_ == false)
38+
{
39+
if (block_previous_from_last != nullptr)
40+
{
41+
block_previous_from_last->next_ = nullptr;
42+
}
43+
else
44+
{
45+
internal::block_list_head = nullptr;
46+
}
47+
internal::decreaseHeap(block_list_tail);
48+
}
49+
}
50+
51+
namespace internal
52+
{
53+
54+
void decreaseHeap(MemoryBlock* block_heap_end)
55+
{
56+
if (block_heap_end == nullptr)
57+
{
58+
return;
59+
}
60+
if (block_heap_end->next_ != nullptr)
61+
{
62+
return;
63+
}
64+
65+
size_t release_size = block_heap_end->size_ + BLOCK_METADATA_SIZE;
66+
void* program_break = sbrk(-static_cast<intptr_t>(release_size));
67+
68+
if (program_break == getErrorCodeInVoidPtr(-1) || program_break == getErrorCodeInVoidPtr(0))
69+
{
70+
exit(-1);
71+
}
72+
73+
total_memory_allocated -= release_size;
74+
}
75+
76+
void mergeFreeMemoryBlocks()
77+
{
78+
MemoryBlock* current = block_list_head;
79+
while (current != nullptr && current->next_ != nullptr)
80+
{
81+
if (current->allocated_ == false && current->next_->allocated_ == false)
82+
{
83+
current->size_ += BLOCK_METADATA_SIZE + current->next_->size_;
84+
current->next_ = current->next_->next_;
85+
}
86+
else
87+
{
88+
current = current->next_;
89+
}
90+
}
91+
}
92+
93+
void getLastMemoryBlock(MemoryBlock** block_list_tail, MemoryBlock** block_previous_from_last)
94+
{
95+
MemoryBlock* current = block_list_head;
96+
MemoryBlock* previous = nullptr;
97+
98+
while (current != nullptr && current->next_ != nullptr)
99+
{
100+
previous = current;
101+
current = current->next_;
102+
}
103+
104+
*block_list_tail = current;
105+
*block_previous_from_last = previous;
12106
}
13107

108+
} // namespace internal
14109
} // namespace mem

0 commit comments

Comments
 (0)