使用 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
问题:
我需要 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