malloc:释放对象的校验和不正确 0x7fd4f4c8bbd0:可能在释放后被修改

malloc: Incorrect checksum for freed object 0x7fd4f4c8bbd0: probably modified after being freed

我正在尝试编写一个解析器来导入 OBJ 文件,但即使在这个早期阶段,我在执行时遇到以下错误:

malloc: Incorrect checksum for freed object 0x7fd4f4c8bbd0: probably modified after being freed.

它设法打印每行的缓冲区大小,所以我想知道问题是否与操作后关闭文件有关。

有人能告诉我我做错了什么吗?我在 macOS 运行。

int Utilities_Import_OBJ(const char *filename) {
    // input checking
    if (filename == NULL) {
        printf("Unable to parse file, filename was NULL.\n");
        return -1;
    }

    char *path = strcat(_resource_path, filename);

    FILE *file = fopen(path, "r");
    if (file == NULL) {
        printf("Error opening %s\n", filename);
        return -1;
    }

    // create a line buffer
    const int length = 1024;
    char buffer[length];

    int index = 0;

    // fgets stops reading at a \n and appends [=11=]   
    while (fgets(buffer, sizeof(buffer), file)) {
        printf("Buffer size at line %d : %d\n", index, sizeof(buffer));
        index++;
    }

    // done with file, so close it
    if (fclose(file) != 0) {
        printf("Failed to close file!\n");
        return -1;
    }

    return 0;
}

您的代码中有 2 行令人惊讶:

  • char *path = strcat(_resource_path, filename);

    strcat 不会将 2 个字符串连接成第三个分配的字符串。它在第一个字符串的末尾复制第二个字符串。根据 _resource_path 的分配方式,这一行很可能会破坏 malloc() 内部数据并最终产生问题。你应该像这样写一个特定的函数:

    char *concat(const char *s1, const char *s2) {
        size_t len1 = strlen(s1);
        size_t len2 = strlen(s2);
        char *p = malloc(len1 + len2 + 1);
        if (p) {
            memcpy(p, s1, len1);
            memcpy(p + len1, s2, len2 + 1);
        }
        return p;
    }
    

    你会 free 使用后 char *path = concat(_resource_path, filename); 返回的字符串。

  • printf("Buffer size at line %d : %d\n", index, sizeof(buffer));

    缓冲区大小是恒定的,sizeof(buffer) 始终计算为 lengthbuffer 定义时的值 (1024)。此外,您应该将 %zu 用于 size_t 参数,而不是 %d,它需要一个可能具有不同大小的 int。你可能想这样写:

    printf("Buffer length at line %d: %zu\n", index, strlen(buffer));