使用 free() 会损坏 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: %sn",names[0]);
free(extension_names);
printf("First extension available: %sn",names[0]);
return 0;}

结果如下:

在自由之前((

第一个可用的扩展名:VK_KHR_device_group_creation

释放后((

第一个可用的扩展:yUU

您可以使用 strdup 制作字符串的副本并解决您遇到的"释放后使用"问题:

#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: %sn", names[0]);
    free(extension_names);
    printf("First extension available: %sn", names[0]);
    return 0;
}

输出

First extension available: extension000
First extension available: extension000

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

有用的海湾合作委员会标志

当我引起您的注意时,不要忘记使用-Wall -Werror编译代码,以帮助您在编译时解决问题:

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

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

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

您只能在使用完names后释放extension_names

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

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

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

最新更新