aboutsummaryrefslogtreecommitdiffstats
path: root/src/free.c
diff options
context:
space:
mode:
authorThomas Vanbesien <tvanbesi@proton.me>2026-02-27 11:45:06 +0100
committerThomas Vanbesien <tvanbesi@proton.me>2026-02-27 11:45:06 +0100
commit5ba7a73f97fe6880dc5328807a1cb9353e77b863 (patch)
treeeecedfad2887dc717d1771ed3e7a9bc8b7ba1ff7 /src/free.c
parentfb19b1c35f6ec52c075b214d2f0416900a7c1bbe (diff)
downloadmalloc-5ba7a73f97fe6880dc5328807a1cb9353e77b863.tar.gz
malloc-5ba7a73f97fe6880dc5328807a1cb9353e77b863.zip
Implement free and add testing notes to README
free now locates the chunk matching the pointer, marks it as free for TINY/SMALL zones, and munmaps LARGE allocations. Document why ASan is incompatible and list alternatives.
Diffstat (limited to 'src/free.c')
-rw-r--r--src/free.c61
1 files changed, 57 insertions, 4 deletions
diff --git a/src/free.c b/src/free.c
index 22c3faa..0e64b51 100644
--- a/src/free.c
+++ b/src/free.c
@@ -1,14 +1,67 @@
/**
* @file free.c
- * @brief Stub implementation of free.
+ * @brief free implementation.
*/
-#include "libft.h"
#include "malloc.h"
+#include "malloc_internal.h"
+#include <sys/mman.h>
+
+static t_chunk *
+_s_find_chunk (t_zone *zone, void *ptr)
+{
+ t_chunk *chunk;
+
+ while (zone)
+ {
+ chunk = (t_chunk *)((char *)zone + ALIGN (sizeof (t_zone)));
+ while (chunk)
+ {
+ if ((char *)chunk + ALIGN (sizeof (t_chunk)) == ptr)
+ return (chunk);
+ chunk = chunk->next;
+ }
+ zone = zone->next;
+ }
+ return (NULL);
+}
+
+static void
+_s_unlink_zone (t_zone **zone_list, t_zone *zone)
+{
+ t_zone *prev;
+
+ if (*zone_list == zone)
+ {
+ *zone_list = zone->next;
+ return;
+ }
+ prev = *zone_list;
+ while (prev && prev->next != zone)
+ prev = prev->next;
+ if (prev)
+ prev->next = zone->next;
+}
void
free (void *ptr)
{
- (void)ptr;
- ft_putendl_fd ("FREE", 1);
+ t_chunk *chunk;
+ t_zone *zone;
+
+ if (!ptr)
+ return;
+ chunk = _s_find_chunk (g_heap.large, ptr);
+ if (chunk)
+ {
+ zone = (t_zone *)((char *)chunk - ALIGN (sizeof (t_zone)));
+ _s_unlink_zone (&g_heap.large, zone);
+ munmap (zone, zone->size);
+ return;
+ }
+ chunk = _s_find_chunk (g_heap.tiny, ptr);
+ if (!chunk)
+ chunk = _s_find_chunk (g_heap.small, ptr);
+ if (chunk)
+ chunk->is_free = 1;
}