排查C语言中‘pointer being freed was not allocated’错误
问题分析:释放未分配指针错误原因及修复
问题描述
我自行实现了一个哈希表(map),采用SDL内存函数替代标准malloc/free。当前遇到的问题是:第一次调用Map_Set可以正常工作,但使用相同键再次调用时,本该释放旧值并存储新值,却触发了pointer being freed was not allocated错误。我明明做了内存分配,不清楚错误出在哪里。
错误输出
DEBUG: test/src/util/map.c:53:Map_Create(): Map created 0 of 10 used. DEBUG: test/src/util/map.c:101:Map_Set(): Add item 3 of 10. DEBUG: test/src/util/map.c:89:Map_Set(): Free item 3 of 10. sdl_test(19543,0x1ffee1e00) malloc: *** error for object 0x10249bf8e: pointer being freed was not allocated
相关代码
main.c
#include <SDL3/SDL.h> #include <SDL3/SDL_main.h> #include "util/map.h" int main(int argc, char *argv[]) { char *itemA = SDL_malloc(sizeof(char) * 12); char *itemB = SDL_malloc(sizeof(char) * 11); itemA = "Hello World"; itemB = "What's Up?"; Map map = Map_Create(10); Map_Set(map, "test", itemA, SDL_free); Map_Set(map, "test", itemB, SDL_free); Map_Destroy(map); SDL_Quit(); }
map.c
#include <SDL3/SDL.h> #include <SDL3/SDL_assert.h> #include "util/map.h" #include "debug.h" struct Map_Item { struct Map_Item *next; void (*free)(void*); void *value; char *key; } Map_Item; struct Map { struct Map_Item **items; int capacity; int size; }; /** * Internal functions */ static unsigned int _Map_Hash(const char *key) { unsigned int hash = -1; while (*key) { hash *= 31; hash ^= (unsigned char) *key; key += 1; } return hash; } /** * Public functions */ Map Map_Create(int capacity) { Map map = SDL_malloc(sizeof (Map)); SDL_assert(map != NULL); // Create space for the initial items map->items = SDL_calloc(capacity, sizeof (struct Map_Item *)); SDL_assert(map->items != NULL); map->capacity = capacity; map->size = 0; // Clear each location as there is currently nothing in any of them for (int i = 0; i < map->capacity; i += 1) { map->items[i] = NULL; } DEBUG_PRINT("Map created %d of %d used.\n", map->size, map->capacity); return map; } void Map_Destroy(Map map) { DEBUG_PRINT("Map cleanup %d of %d used.\n", map->size, map->capacity); // Loop over each item and free it; for (int i = 0; i < map->capacity; i += 1) { struct Map_Item *curr = map->items[i]; while (curr != NULL) { DEBUG_PRINT("Free item %d of %d.\n", i, map->capacity); struct Map_Item *next = curr->next; if (curr->free != NULL) { curr->free(curr->value); } SDL_free(curr->key); SDL_free(curr); curr = next; } } SDL_free(map->items); SDL_free(map); } void Map_Set(Map map, const char *key, void *value, void (*free)(void*)) { int b = _Map_Hash(key) % map->capacity; // Look if the key is in use, if it is then free the old value and store the // new one in its place. for (struct Map_Item *curr = map->items[b]; curr != NULL; curr = curr->next) { if (SDL_strcmp(curr->key, key) == 0) { if (curr->free != NULL) { DEBUG_PRINT("Free item %d of %d.\n", b, map->capacity); curr->free(curr->value); } DEBUG_PRINT("Replace item %d of %d.\n", b, map->capacity); curr->value = value; curr->free = free; return; } } // No existing key was found, so insert it as a new entry at the head of the // list. DEBUG_PRINT("Add item %d of %d.\n", b, map->capacity); struct Map_Item *new = SDL_malloc(sizeof (struct Map_Item)); new->key = SDL_malloc(sizeof(char) * SDL_strlen(key) + 1); new->next = map->items[b]; new->value = value; new->free = free; SDL_strlcpy(new->key, key, SDL_strlen(key) + 1); map->items[b] = new; map->size += 1; }
错误原因及修复
1. 字符串字面量覆盖堆指针(直接触发错误)
在main.c中,你先通过SDL_malloc为itemA和itemB分配了堆内存,但随后直接将字符串字面量(如"Hello World")赋值给这两个指针。字符串字面量存储在只读数据段,不属于堆内存,当你调用SDL_free释放它们时,必然触发“释放未分配指针”的错误。同时,之前SDL_malloc分配的堆内存也会丢失,造成内存泄漏。
修复:
用SDL_strlcpy将字符串字面量复制到堆分配的内存中,而非直接赋值指针:
char *itemA = SDL_malloc(sizeof(char) * 12); char *itemB = SDL_malloc(sizeof(char) * 11); SDL_strlcpy(itemA, "Hello World", 12); SDL_strlcpy(itemB, "What's Up?", 11);
2. Map_Create中的内存分配隐患
你在Map_Create中使用SDL_malloc(sizeof(Map)),若Map是struct Map*的typedef,当前代码没问题;但如果是struct Map的直接typedef,就会只分配指针大小的内存,导致结构体数据越界。
修复:
显式指定分配struct Map的大小,避免歧义:
Map map = SDL_malloc(sizeof(struct Map));
3. 哈希函数初始值不合理
哈希函数初始值设为unsigned int hash = -1;,unsigned类型的-1会被解析为最大值,可能导致哈希值计算时溢出或分布不佳,影响哈希表性能。
修复:
改用常规的初始值0,并调整哈希计算逻辑:
static unsigned int _Map_Hash(const char *key) { unsigned int hash = 0; while (*key) { hash = hash * 31 + (unsigned char)*key; key += 1; } return hash; }
内容的提问来源于stack exchange,提问作者Justin808
相关产品推荐
相关产品推荐

