提问人:Justin808 提问时间:10/27/2023 更新时间:10/27/2023 访问量:45
试图理解 C 语言中的“未分配指针”错误
Trying to understand a `pointer being freed was not allocated` error in C
问:
所以这个错误是不言自明的,但我不明白我是怎么得到它的。我做了 malloc,现在免费抱怨。
我正在尝试为自己构建一个地图/哈希表。我对 C 不熟悉,但不编程,所以我认为这将是一个不错的开始。我也在使用 SDL,因此我使用这些函数而不是直接的 malloc/free。但这不应该改变任何事情......
因此,我可以创建底图,并可以向其添加键/值。我将 free 函数与它一起存储,以便地图知道如何释放自己的项目。第一组有效。当我使用相同的键再次设置时,它应该释放当前值并存储新值。但这就是错误发生的地方。
我所有的错误在哪里/我做错了什么?
输出
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();
}
地图.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;
}
答:
3赞
John Bollinger
10/27/2023
#1
这里。。。
char *itemA = SDL_malloc(sizeof(char) * 12); char *itemB = SDL_malloc(sizeof(char) * 11);
...为 的两个数组分配内存,并将指向 和 中分配的空间的指针存储在 中。char
itemA
itemB
这里。。。
itemA = "Hello World"; itemB = "What's Up?";
...将指向已分配空间的指针替换为指向字符串文本的指针(泄漏已分配的内存)。这些确实不是动态分配的。当你试图释放其中一个时,系统完全有理由抱怨。
您可能希望将数据复制到分配的块中,而不是将项目指向不同的对象。那就是:
strcpy(itemA, "Hello World");
strcpy(itemB, "What's Up?");
评论
itemA = "Hello World";
立即关闭刚刚分配的 PTR。同样......您可能希望 Haven Haven 阅读其余代码。(PS:不要吝啬缓冲区大小。有 GB 的 RAM 感觉被忽视了,同时想要有用。PPS:你没有检查从...总有一天它会咬你!现在就养成习惯吧!itemB
strcpy( itemA, "Hello World" );
malloc()
strdup()
*alloc
void *xmalloc(size_t size) { void *ptr = malloc(size); if (ptr == NULL) { perror("xmalloc"); exit(1); } return ptr; }
:-)