将内存分配给 const char*** 变量时出错 "realloc(): invalid next size"
ERROR "realloc(): invalid next size" when allocating memory to const char*** variable
我有一个功能
populateAvailableExtensions(const char** gAvailableExtensions[], int gCounter)
它以指向字符串数组的指针和数组中元素的数量作为参数。
我使用 malloc(0)
为该数组分配了初始内存。规范说它将 return 一个空指针或一个可以传递给 free()
.
的唯一指针
int currentAvailableExtensionCount = gCounter;
此变量将存储 gAvailableExtensions
中的字符串数。
在这个 for
循环中
for (int i = 0; i < availableExtensionCount; ++i)
我有这段代码
size_t sizeOfAvailableExtensionName =
sizeof(availableExtensionProperties[i].name);
reallocStatus = realloc(*gAvailableExtensions, sizeOfAvailableExtensionName);
memcpy(&(*gAvailableExtensions)[currentAvailableExtensionCount],
&availableExtensionProperties[i].name,
sizeOfAvailableExtensionName);
++currentAvailableExtensionCount;
其中
availableExtensionProperties[i].name
return一个字符串。
这就是 struct
的定义方式
typedef struct Stuff {
char name[MAX_POSSIBLE_NAME];
...
...
} Stuff;
realloc(*gAvailableExtensions, sizeOfAvailableExtensionName);
应该将大小为 sizeOfAvailableExtensionName
的内存添加到 *gAvailableExtensions
取消引用的数组。
memcpy(&(*gAvailableExtensions)[currentAvailableExtensionCount],
&availableExtensionProperties[i].name,
sizeOfAvailableExtensionName);
应该从
复制字符串(这sizeOfAvailableExtensionName
很多内存)
&availableExtensionPropterties[i].name
地址
&(*gAvailableExtensions)[currentAvailableExtensionCount]
地址。
但我认为代码没有按照我的想法执行,因为我遇到了这个错误
realloc(): invalid next size
Aborted
(core dumped) ./Executable
编辑:完整代码
uint32_t populateAvailableExtensions(const char** gAvailableExtensions[], int gCounter) {
int currentAvailableExtensionCount = gCounter;
void* reallocStatus;
uint32_t availableExtensionCount = 0;
vkEnumerateInstanceExtensionProperties(
VK_NULL_HANDLE, &availableExtensionCount, VK_NULL_HANDLE);
VkExtensionProperties availableExtensionProperties[availableExtensionCount];
vkEnumerateInstanceExtensionProperties(
VK_NULL_HANDLE, &availableExtensionCount, availableExtensionProperties);
for (int i = 0; i < availableExtensionCount; ++i) {
size_t sizeOfAvailableExtensionName =
sizeof(availableExtensionProperties[i].extensionName);
reallocStatus = realloc(*gAvailableExtensions, sizeOfAvailableExtensionName);
memcpy(&(*gAvailableExtensions)[currentAvailableExtensionCount],
availableExtensionProperties[i].extensionName,
sizeOfAvailableExtensionName);
++currentAvailableExtensionCount;
}
return currentAvailableExtensionCount;
}
这是外部函数调用该函数的方式,
uint32_t availableExtensionCount = 0;
availableExtensions = malloc(0);
availableExtensionCount = populateAvailableExtensions(&availableExtensions);
和
const char** availableExtensions;
在头文件中声明。
编辑 2:更新了代码,现在 gCounter
包含 gAvailableExtensions
中的元素数
int currentAvailableExtensionCount =
sizeof(*gAvailableExtensions) / sizeof(**gAvailableExtensions) - 1;
只是
的一种混淆方式
int currentAvailableExtensionCount = 0;
之后我就停止阅读了,因为我认为那不是你打算写的。
c
中的指针不知道它们指向的序列中有多少个元素。他们只知道单个元素的大小。
在您的例子中,*gAvailableExtensions
是 char **
类型,**gAvailableExtensions
是 char *
类型。两者都是指针,在典型的桌面系统上具有相同的大小。所以在 64 位桌面系统上表达式变成
8/8 - 1
,等于零。
除非您修复此错误,或者明确您确实希望该值始终为零,否则其余代码没有任何意义。
这个循环完全是乱七八糟的:
for (int i = 0; i < availableExtensionCount; ++i) {
size_t sizeOfAvailableExtensionName =
sizeof(availableExtensionProperties[i].extensionName);
reallocStatus = realloc(*gAvailableExtensions, sizeOfAvailableExtensionName);
memcpy(&(*gAvailableExtensions)[currentAvailableExtensionCount],
availableExtensionProperties[i].extensionName,
sizeOfAvailableExtensionName);
++currentAvailableExtensionCount;
}
我假设只有行会按照您的期望行事,行是行 for (int i = 0; i < availableExtensionCount; ++i)
和 ++currentAvailableExtensionCount;
首先,realloc
的典型使用方式是这样的:
foo *new_p = realloc(p, new_size);
if (!new_p)
handle_error();
else
p = new_p;
要点是,如果发生重新分配,realloc
将不会更新 p
的值。更新 'p' 是你的责任。在您的情况下,您永远不会更新 *gAvailableExtensions
。我还怀疑你没有正确计算 sizeOfAvailableExtensionCount
。运算符 sizeof
总是 return 编译时间常量,因此 realloc
实际上没有任何意义。
memcpy
实际上也没有任何意义,因为您正在将字符串复制到指针数组的内存中(可能有额外的缓冲区溢出)。
你说 *gAvailableExtensions
是一个指向字符串指针数组的指针。
这意味着您必须 realloc
缓冲区来保存正确数量的指针,并且 malloc
内存用于您要存储的每个字符串。
对于这个例子,我假设 .extensionName
的类型是 char *
或 char[XXX]
:
// Calculate new size of pointer array
// TODO: Check for overflow
size_t new_array_size =
(currentAvailableExtensionCount + availableExtensionCount) * sizeof(*gAvailableExtensions);
char **tmp_ptr = realloc(*gAvailableExtensions, new_array_size);
if (!tmp_ptr)
{
//TODO: Handle error;
return currentAvailableExtensionCount;
}
*gAvailableExtensions = tmp_ptr;
// Add strings to array
for (int i = 0; i < availableExtensionCount; ++i)
{
size_t length = strlen(availableExtensionProperties[i].extensionName);
// Allocate space for new string
char *new_s = malloc(length + 1);
if (!new_s)
{
//TODO: Handle error;
return currentAvailableExtensionCount;
}
// Copy string
memcpy (new_s, availableExtensionProperties[i].extensionName, length + 1);
// Insert string in array
(*gAvailableExtensions)[currentAvailableExtensionCount] = new_s;
++currentAvailableExtensionCount;
}
如果你能保证 availableExtensionProperties[i].extensionName
的生命周期比 *gAvailableExtensions
长,你可以通过在循环中删除 malloc
和 memcpy
来稍微简化一下,然后做:
char *new_s = availableExtensionProperties[i].extensionName;
(*gAvailableExtensions)[currentAvailableExtensionCount] = new_s;
最后说句狠话:看来你有"Infinite number of Monkeys"的编程方法,敲键盘就可以了。
这样的程序只会给人一种工作的错觉。他们迟早会以惊人的方式打破。
编程不是猜谜游戏。您必须 理解您编写的每一段代码,然后再转到下一段代码。
我有一个功能
populateAvailableExtensions(const char** gAvailableExtensions[], int gCounter)
它以指向字符串数组的指针和数组中元素的数量作为参数。
我使用 malloc(0)
为该数组分配了初始内存。规范说它将 return 一个空指针或一个可以传递给 free()
.
int currentAvailableExtensionCount = gCounter;
此变量将存储 gAvailableExtensions
中的字符串数。
在这个 for
循环中
for (int i = 0; i < availableExtensionCount; ++i)
我有这段代码
size_t sizeOfAvailableExtensionName =
sizeof(availableExtensionProperties[i].name);
reallocStatus = realloc(*gAvailableExtensions, sizeOfAvailableExtensionName);
memcpy(&(*gAvailableExtensions)[currentAvailableExtensionCount],
&availableExtensionProperties[i].name,
sizeOfAvailableExtensionName);
++currentAvailableExtensionCount;
其中
availableExtensionProperties[i].name
return一个字符串。
这就是 struct
的定义方式
typedef struct Stuff {
char name[MAX_POSSIBLE_NAME];
...
...
} Stuff;
realloc(*gAvailableExtensions, sizeOfAvailableExtensionName);
应该将大小为 sizeOfAvailableExtensionName
的内存添加到 *gAvailableExtensions
取消引用的数组。
memcpy(&(*gAvailableExtensions)[currentAvailableExtensionCount],
&availableExtensionProperties[i].name,
sizeOfAvailableExtensionName);
应该从
复制字符串(这sizeOfAvailableExtensionName
很多内存)
&availableExtensionPropterties[i].name
地址
&(*gAvailableExtensions)[currentAvailableExtensionCount]
地址。
但我认为代码没有按照我的想法执行,因为我遇到了这个错误
realloc(): invalid next size
Aborted
(core dumped) ./Executable
编辑:完整代码
uint32_t populateAvailableExtensions(const char** gAvailableExtensions[], int gCounter) {
int currentAvailableExtensionCount = gCounter;
void* reallocStatus;
uint32_t availableExtensionCount = 0;
vkEnumerateInstanceExtensionProperties(
VK_NULL_HANDLE, &availableExtensionCount, VK_NULL_HANDLE);
VkExtensionProperties availableExtensionProperties[availableExtensionCount];
vkEnumerateInstanceExtensionProperties(
VK_NULL_HANDLE, &availableExtensionCount, availableExtensionProperties);
for (int i = 0; i < availableExtensionCount; ++i) {
size_t sizeOfAvailableExtensionName =
sizeof(availableExtensionProperties[i].extensionName);
reallocStatus = realloc(*gAvailableExtensions, sizeOfAvailableExtensionName);
memcpy(&(*gAvailableExtensions)[currentAvailableExtensionCount],
availableExtensionProperties[i].extensionName,
sizeOfAvailableExtensionName);
++currentAvailableExtensionCount;
}
return currentAvailableExtensionCount;
}
这是外部函数调用该函数的方式,
uint32_t availableExtensionCount = 0;
availableExtensions = malloc(0);
availableExtensionCount = populateAvailableExtensions(&availableExtensions);
和
const char** availableExtensions;
在头文件中声明。
编辑 2:更新了代码,现在 gCounter
包含 gAvailableExtensions
int currentAvailableExtensionCount =
sizeof(*gAvailableExtensions) / sizeof(**gAvailableExtensions) - 1;
只是
的一种混淆方式int currentAvailableExtensionCount = 0;
之后我就停止阅读了,因为我认为那不是你打算写的。
c
中的指针不知道它们指向的序列中有多少个元素。他们只知道单个元素的大小。
在您的例子中,*gAvailableExtensions
是 char **
类型,**gAvailableExtensions
是 char *
类型。两者都是指针,在典型的桌面系统上具有相同的大小。所以在 64 位桌面系统上表达式变成
8/8 - 1
,等于零。
除非您修复此错误,或者明确您确实希望该值始终为零,否则其余代码没有任何意义。
这个循环完全是乱七八糟的:
for (int i = 0; i < availableExtensionCount; ++i) {
size_t sizeOfAvailableExtensionName =
sizeof(availableExtensionProperties[i].extensionName);
reallocStatus = realloc(*gAvailableExtensions, sizeOfAvailableExtensionName);
memcpy(&(*gAvailableExtensions)[currentAvailableExtensionCount],
availableExtensionProperties[i].extensionName,
sizeOfAvailableExtensionName);
++currentAvailableExtensionCount;
}
我假设只有行会按照您的期望行事,行是行 for (int i = 0; i < availableExtensionCount; ++i)
和 ++currentAvailableExtensionCount;
首先,realloc
的典型使用方式是这样的:
foo *new_p = realloc(p, new_size);
if (!new_p)
handle_error();
else
p = new_p;
要点是,如果发生重新分配,realloc
将不会更新 p
的值。更新 'p' 是你的责任。在您的情况下,您永远不会更新 *gAvailableExtensions
。我还怀疑你没有正确计算 sizeOfAvailableExtensionCount
。运算符 sizeof
总是 return 编译时间常量,因此 realloc
实际上没有任何意义。
memcpy
实际上也没有任何意义,因为您正在将字符串复制到指针数组的内存中(可能有额外的缓冲区溢出)。
你说 *gAvailableExtensions
是一个指向字符串指针数组的指针。
这意味着您必须 realloc
缓冲区来保存正确数量的指针,并且 malloc
内存用于您要存储的每个字符串。
对于这个例子,我假设 .extensionName
的类型是 char *
或 char[XXX]
:
// Calculate new size of pointer array
// TODO: Check for overflow
size_t new_array_size =
(currentAvailableExtensionCount + availableExtensionCount) * sizeof(*gAvailableExtensions);
char **tmp_ptr = realloc(*gAvailableExtensions, new_array_size);
if (!tmp_ptr)
{
//TODO: Handle error;
return currentAvailableExtensionCount;
}
*gAvailableExtensions = tmp_ptr;
// Add strings to array
for (int i = 0; i < availableExtensionCount; ++i)
{
size_t length = strlen(availableExtensionProperties[i].extensionName);
// Allocate space for new string
char *new_s = malloc(length + 1);
if (!new_s)
{
//TODO: Handle error;
return currentAvailableExtensionCount;
}
// Copy string
memcpy (new_s, availableExtensionProperties[i].extensionName, length + 1);
// Insert string in array
(*gAvailableExtensions)[currentAvailableExtensionCount] = new_s;
++currentAvailableExtensionCount;
}
如果你能保证 availableExtensionProperties[i].extensionName
的生命周期比 *gAvailableExtensions
长,你可以通过在循环中删除 malloc
和 memcpy
来稍微简化一下,然后做:
char *new_s = availableExtensionProperties[i].extensionName;
(*gAvailableExtensions)[currentAvailableExtensionCount] = new_s;
最后说句狠话:看来你有"Infinite number of Monkeys"的编程方法,敲键盘就可以了。
这样的程序只会给人一种工作的错觉。他们迟早会以惊人的方式打破。
编程不是猜谜游戏。您必须 理解您编写的每一段代码,然后再转到下一段代码。