Linux Ubuntu 16.04自定义内存分配器出现段错误(核心已转储)求助
Hey there! Let's break down the segmentation fault issues in your custom memory allocator—since this is your first time building one, it's totally normal to hit these snags. I’ve gone through your code and found a few critical bugs that are almost certainly causing the crash, plus some improvements to make it more robust.
Key Issues & Fixes
1. Uninitialized Mutex Lock
This is likely the primary cause of your segmentation fault. You declared the global mutex global_malloc_lock but never initialized it. Calling pthread_mutex_lock or pthread_mutex_unlock on an uninitialized mutex triggers undefined behavior, which often leads to crashes.
Fix:
Use static initialization for the mutex (simpler and safer for global variables):
// Replace the original declaration with this pthread_mutex_t global_malloc_lock = PTHREAD_MUTEX_INITIALIZER;
Alternatively, you could call pthread_mutex_init(&global_malloc_lock, NULL); at the start of your program (e.g., in main), but static initialization is cleaner here.
2. Infinite Loop & Null Pointer Dereference in free()
When freeing the last block in your linked list, your loop to find the new tail has a logic flaw: once you locate the node before the tail, you don't exit the loop. This causes tmp to eventually become NULL, and the next iteration tries to access tmp->next, which is a null pointer dereference—boom, segmentation fault.
Original problematic code:
tmp = head; while (tmp) { if(tmp->next == tail) { tmp->next = NULL; tail = tmp; } tmp = tmp->next; // Keeps looping even after finding the node }
Fixed code:
tmp = head; while (tmp) { if(tmp->next == tail) { tmp->next = NULL; tail = tmp; break; // Exit loop immediately after updating the tail } tmp = tmp->next; }
3. Missing Validation in realloc()
If someone passes a pointer not allocated by your custom malloc to realloc, the line header = (struct header_t*)block - 1 will create an invalid pointer. Accessing header->size with this invalid pointer will cause a crash. While you might only use your allocator internally, adding validation makes it more robust.
Fix (add magic number validation):
First, update the header_t struct to include a magic number:
struct header_t { size_t size; unsigned is_free; struct header_t *next; unsigned int magic; // Add a unique magic number for validation };
Then set the magic number when creating new blocks in malloc:
header = block; header->size = size; header->is_free = 0; header->next = NULL; header->magic = 0xDEADBEEF; // Set a unique value
Finally, add validation in realloc and free:
// In realloc() header = (struct header_t*)block - 1; if (header->magic != 0xDEADBEEF) { pthread_mutex_unlock(&global_malloc_lock); return NULL; // Invalid block, return error } // In free() header = (struct header_t*)block - 1; if (header->magic != 0xDEADBEEF) { pthread_mutex_unlock(&global_malloc_lock); return; // Invalid block, exit early }
4. Thread Safety Risk with sbrk()
As you noted in your comments, sbrk() isn't thread-safe. Even with your global mutex, if any other code (like a library function) calls sbrk() behind your back, it can corrupt your heap. For a more thread-safe alternative, consider using mmap() to allocate memory instead of sbrk().
Bonus: Reduce Memory Fragmentation
Once you fix the crashes, you might want to add free block coalescing: when freeing a block, check if adjacent blocks are also free and merge them into a single larger block. This prevents your heap from getting split into tiny unusable chunks over time.
内容的提问来源于stack exchange,提问作者Maxim Kogan

