diff options
| author | Thomas Vanbesien <tvanbesi@proton.me> | 2026-02-27 11:45:06 +0100 |
|---|---|---|
| committer | Thomas Vanbesien <tvanbesi@proton.me> | 2026-02-27 11:45:06 +0100 |
| commit | 5ba7a73f97fe6880dc5328807a1cb9353e77b863 (patch) | |
| tree | eecedfad2887dc717d1771ed3e7a9bc8b7ba1ff7 | |
| parent | fb19b1c35f6ec52c075b214d2f0416900a7c1bbe (diff) | |
| download | malloc-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.
| -rw-r--r-- | README.md | 16 | ||||
| -rw-r--r-- | src/free.c | 61 |
2 files changed, 73 insertions, 4 deletions
@@ -53,3 +53,19 @@ are allocated on demand when the current one is full. LARGE allocations each get their own `mmap` region and are released individually via `munmap`. All returned pointers are 16-byte aligned. + +## Testing + +AddressSanitizer (ASan) cannot be used to test this allocator. ASan intercepts +`malloc`/`free` itself and expects specific allocator metadata (redzones, +quarantine zones) that a custom allocator does not provide. The two +implementations would conflict. Since allocations go through `mmap`, they also +bypass ASan's shadow memory tracking entirely. + +Alternatives for catching bugs: +- **Valgrind** — operates at the binary level without replacing `malloc`, so it + can detect issues in the allocator's own internal logic. +- **Custom tests** — targeted checks for write-after-free, double free, boundary + writes, and stress scenarios. +- **`show_alloc_mem()`** — inspect zone and chunk state visually after + operations. @@ -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; } |
