重新分配错误但不是malloc?

Posted

技术标签:

【中文标题】重新分配错误但不是malloc?【英文标题】:Error in realloc but not malloc? 【发布时间】:2014-03-03 23:40:28 【问题描述】:

我不得不使用其他人的代码,因此我无法完全控制我可以更改的内容,但我想知道为什么会出现此错误,并希望得到任何建议。这段代码在我无法更改的部分,但我需要确保我编写的部分(StringRef 类)有效。

它给我的错误是“X 处的堆块在 Y 超过请求的 28 大小时修改”。如果我将使用 realloc 的现有代码更改为 malloc ,它会稍微降低罐头并将更多值加载到数组中。这是有问题的行。我不能包含所有代码,因为它太广泛了。这些信息是否足以诊断我做错了什么?

struct StringList

    StringRef *elements;
    unsigned int count;
;

.....

// Append the given StringRef to the list.
bool StringListAppend(StringList& self, StringRef p_string)


    StringRef *t_new_elements;
    t_new_elements = (StringRef *)realloc(self.elements, (self.count + 1) * sizeof(StringRef *));
    if (t_new_elements == NULL)
        return false;

    self.elements = t_new_elements;
    std::cout<<self.count<<"\n";
    // Initialize and assign the new element.
    StringInitialize(self.elements[self.count]);
    if (!StringAssign(self.elements[self.count], p_string))
        return false;

    // We've successfully added the element, so bump the count.
    self.count += 1;

    return true;

StringRef *t_new_elements;
t_new_elements = (StringRef *)malloc((self.count + 1) * sizeof(StringRef *));

对于带有 realloc 的行可以进一步避免问题。

【问题讨论】:

你了解reallocmalloc的区别吗?如果不是,您可能应该先这样做。 realloc 将复制分配的旧内容,malloc 不会。将代码更改为使用malloc 完全泄露了之前的分配,也忘记了self.elements 之前的所有内容。不要“把罐子踢到路上”。找出真正的错误(缓冲区溢出)并修复它 这段代码唯一符合 C++ 条件的两件事是使用std::cout 和一个引用。如果有人称它为 C++,我会为你感到难过。 我确实“基本上”了解它们之间的区别。我只是想对现有代码进行足够的修改,以使我编写的代码可以运行或不运行。我对 C++ 有点熟悉(但生疏)。我知道有些人在用 C++ 编码时喜欢使用一个/或/两个(正如这段代码的作者所做的那样)。我不知道如何追踪缓冲区溢出,除了我已经在做的改变可能是问题的因素并试图追踪错误的来源。 realloc 可用于 1) 分配内存块 2) 调整成员块的大小和 3) 释放内存块。出于这个原因,在您的代码中单独使用realloc 非常舒服,但要小心!在某些平台上realloc将现有块大小为零frees 块,而在其他一些平台上它只返回一个大小为零的块,该块必须稍后是freed。 @pasztorpisti - 代码的作者只是用它来调整数组的大小,所以它不应该在这里产生副作用。 【参考方案1】:

sizeof(StringRef *) 应该是sizeof(StringRef)

你可以通过使用这个成语来避免这个错误:

ptr = realloc(old_ptr, n_elements * sizeof *ptr);

当根据保存返回指针的变量的类型确定要分配的字节数时;它不需要您重复任何内容,从而引入差异。

至于为什么将realloc 更改为malloc 会稍微移动程序崩溃的点...未定义的行为是未定义的:)

【讨论】:

【参考方案2】:

假设您希望分配一些内存。 您应该使用 malloc(将内存存储在未初始化的堆上)或 calloc(将所有元素初始化为 0)。 Explained more Here!

Realloc 扩展了您分配的内存的长度。所以你需要先分配一些,然后才能扩展它。 (不要需要,但这样做是很好的编码习惯)Realloc

我建议更多地了解内存分配,因为滥用它会大大降低效率,必须谨慎对待,例如:您应该始终释放在程序结束时分配的内存!

【讨论】:

虽然对问题发布者完全有效并且可能有用,但它不会尝试回答发布的问题。答案需要限制在实际尝试回答问题的范围内。 哈哈不@mah 这么说是对的!我没有真正回答这个问题。我想做的是将 OP 引导到一条以后会更有用的路径,因为现在很容易更改代码而不是 1000 行到他的程序中……尤其是在处理内存分配时。 @πάνταῥεῖ 我并不挑剔,我知道网站的规则是什么——而且我知道在一些人将他的帖子标记为如果不是答案,它将被删除(可能是由版主删除,也可能是自动删除,我不确定它是如何工作的)。由于稻草人对该网站来说相对较新,因此我决定轻推他一下,因为这比看到您的答案消失而没有任何解释要好。 请注意,在将内存传递给realloc 之前,您实际上并不需要分配内存。例如,realloc(NULL, sz) 等价于 malloc(sz) 是的,这就是为什么我在括号中写了“不需要,但这样做是一种很好的编码习惯”:)

以上是关于重新分配错误但不是malloc?的主要内容,如果未能解决你的问题,请参考以下文章

Python3.9 malloc:无法分配区域错误3

为啥在将 malloc() 的指针分配给 char* 时会出现段错误?

使用malloc获取错误来分配内存

malloc中的电子围栏段错误

使 malloc() 返回 NULL 而不是使程序崩溃?

C: 被释放的 malloc 错误指针未被分配