使用 free() 破坏 C 中的 char 数组数据

Using free() corrupts char array data in C

问题:

我需要 malloc 一个结构来填充一个 char *[64] 数组。当我释放结构时,这个数组被破坏了。具体第一个指标。我该如何处理?

int main(void) {
char *names[64];
uint32_t aCount = 0;
uint32_t count = 0;
vkEnumerateInstanceExtensionProperties(NULL,&count, NULL);
VkExtensionProperties *extension_names = malloc(sizeof(VkExtensionProperties) * count);
vkEnumerateInstanceExtensionProperties(NULL,&count,extension_names);

for(uint32_t i = 0; i < count; i++) {
    names[aCount++] = extension_names[i].extensionName;
}

printf("First extension available: %s\n",names[0]);

free(extension_names);

printf("First extension available: %s\n",names[0]);
return 0;}

结果如下:

免费之前()

第一个扩展可用:VK_KHR_device_group_creation

free()后

可用的第一个扩展名:����yUU

您正在分配 names[aCount++] = extension_names[i].extensionName;

即您正在复制 extension_names 指针数组中的 names.

您只能在使用 names

后释放 extension_names

您释放了字符串,所以不确定您预期会发生什么。第二个 printf() 将访问释放的内存。如果你想让字符串保存得更久,你应该复制字符串数据,而不仅仅是指向该数据的指针。此外,您需要编写更安全的代码来避免缓冲区溢出(例如,您没有检查是否在 names 的末尾进行写入。)

for (uint32_t i = 0; i < count && aCount < 64; i++, aCount++) {
    // +1 for the '[=10=]' terminator
    const size_t len = strlen(extension_names[i].extensionName) + 1;

    names[aCount] = malloc(len);
    memcpy(names[aCount], extension_names[i].extensionName, len);
}

请注意,当您不再需要 names 中的每个元素时,您现在还必须 free()

您可以使用 strdup 复制字符串并解决您遇到的 "use after free" 问题:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define UNUSED(x) \
    ((void)(x))

#define VK_MAX_EXTENSION_NAME_SIZE 256

typedef struct VkExtensionProperties {
    char        extensionName[VK_MAX_EXTENSION_NAME_SIZE];
    uint32_t    specVersion;
} VkExtensionProperties;

void vkEnumerateInstanceExtensionProperties(void *unused, 
        uint32_t *count, VkExtensionProperties *result) {
    UNUSED(unused);
    *count = 64;
    if (result) {
        for (int index = 0; index < *count; index++) {
            snprintf(result[index].extensionName, 
                    sizeof(result->extensionName), 
                    "extension%03d", 
                    index);
        }
    }
}

int main()
{
    char *names[64];
    uint32_t aCount = 0;
    uint32_t count = 0;
    vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
    VkExtensionProperties *extension_names = malloc(sizeof(VkExtensionProperties) * count);
    vkEnumerateInstanceExtensionProperties(NULL, &count, extension_names);

    for (uint32_t i = 0; i < count; i++) {
        names[aCount++] = strdup(extension_names[i].extensionName);
    }
    printf("First extension available: %s\n", names[0]);

    free(extension_names);

    printf("First extension available: %s\n", names[0]);

    return 0;
}

输出

First extension available: extension000
First extension available: extension000

我没有安装 Vulcan,所以我模拟了您调用的函数的行为。

有用的 GCC 标志

虽然我引起了你的注意,但不要忘记用 -Wall -Werror 编译你的代码以帮助你在编译时解决问题:

$ gcc -Wall -Werror -o program program.c