所以错误是不言自明的,但我不明白我是怎么得到它的.我做了malloc,现在免费抱怨.

我正试着为自己建立一个映射/哈希表.我对C语言很陌生,但不会编程,所以我想这将是一个很好的开始.我也在使用SDL,所以我使用这些函数,而不是直接使用Malloc/Free.但这不会改变任何事.

这样我就可以创建基本 map ,并为其添加一个键/值.我将免费功能与它一起存储,这样 map 就知道如何释放自己的项目.第一套起作用了.当我用相同的键再次设置时,它应该释放当前值并存储新的值.但这就是错误发生的地方.

Where are all my mistakes / what am I doing wrong?

Output

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;
}

推荐答案

这里...

  char *itemA = SDL_malloc(sizeof(char) * 12);
  char *itemB = SDL_malloc(sizeof(char) * 11);

...您为两个由char组成的数组分配内存,并存储指向itemAitemB中已分配空间的指针.

这里...

  itemA = "Hello World";
  itemB = "What's Up?";

...你用指向字符串文字的指针replace指向分配的空间的指针(泄漏分配的内存). 这些实际上不是动态分配的. 当你试图释放其中一个时,系统完全有理由抱怨.

您可能希望将数据复制到分配的块中,而不是将项目指向不同的对象.这将是:

  strcpy(itemA, "Hello World");
  strcpy(itemB, "What's Up?");

C++相关问答推荐

librsvg rsvg_handle_get_dimensions获取像素大小与浏览器中的渲染大小没有不同

为什么listen()(在调用accept()之前)足以让应用程序完成3次握手?

当多个线程在C中写入相同的文件描述符时,如何防止争用情况?

ZED for SDL上的C语言服务器

如何一次获取一个字符

无效指针值在函数调用之间莫名其妙地改变

为什么GCC C23中的关键字FALSE不是整数常量表达式?

为什么GDB/MI进程的FIFO循环中有read()阻塞

等同于铁 rust 的纯C语言S未实现!()宏

循环中的静态变量与块中的变量和循环

在吉陀罗中,_2_1_和CONCAT11是什么意思?

如何在MSVC中使用intSafe.h函数?

挥发性语义的形式化理解

Ubuntu编译:C中的文件格式无法识别错误

GnuCobol 使用 double 类型的参数调用 C 函数

#define X Defined(Y) 是有效的 C/C++ 宏定义吗?

与 C 相比,C++ 中无副作用的无限循环的好处是 UB?

C23 中的 [[reproducible]] 和 [[unsequenced]] 属性是什么?什么时候应该使用它们?

c 函数指针,另一种语法

这种 C 函数风格的名称是什么?