c - 将内存分配给 const char*** 变量时出现错误“realloc(): invalid next size”
问题描述
我有一个功能
populateAvailableExtensions(const char** gAvailableExtensions[], int gCounter)
它将指向字符串数组的指针和数组中元素的数量作为参数。
我使用malloc(0)
. 规范说它要么返回一个空指针,要么返回一个可以传递给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
返回一个字符串。
这就是它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
解决方案
这个循环非常混乱:
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
总是返回一个编译时间常数,所以realloc
实际上没有任何意义。
memcpy
实际上也没有任何意义,因为您正在将字符串复制到指针数组的内存中(可能还有额外的缓冲区溢出)。
你说这*gAvailableExtensions
是一个指向字符串指针数组的指针。这意味着您必须realloc
在缓冲区中保存正确数量的指针,以及malloc
要存储的每个字符串的内存。
对于这个例子,我假设它.extensionName
的类型是char *
or 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
比 长,您可以通过将and放入循环中*gAvailableExtensions
来简化这一点,并执行以下操作:malloc
memcpy
char *new_s = availableExtensionProperties[i].extensionName;
(*gAvailableExtensions)[currentAvailableExtensionCount] = new_s;
最后用一些刺耳的话:看起来你有“无限数量的猴子”编程方法,只需敲击键盘直到它工作。
这样的程序只会给人一种工作的错觉。它们迟早会以惊人的方式破裂。
编程不是猜谜游戏。在移动到下一个代码之前,您必须了解您编写的每一段代码。
推荐阅读
- c++ - “Ninja”类没有任何名为“Damage”的字段
- c - 如何将数据保存在 file.txt 中?
- ansible - 是否可以在 Ansible 剧本中为 JAR 文件名使用通配符?
- java - 如何“分组” if 语句以在 Android Studio 的微调器中使用?
- dart - 寻找具有不同时区的 2 个 DateTime 对象的差异?
- javascript - Parsley JS 不等于多个 ID
- javascript - 无法添加第二个选择范围(谷歌浏览器)
- c# - 如何将 Firebase 实时数据库连接到我的 C# 项目?
- java - @JsonView 不为 Spark 中部署的 Spring Boot 应用程序渲染
- php - Drupal 8 创建 XML 队列