【问题标题】:Why calloc call might result into memory corruption and malloc works fine为什么 calloc 调用可能会导致内存损坏并且 malloc 工作正常
【发布时间】:2014-10-21 13:07:43
【问题描述】:

我正在使用归并排序编写一个简单的计数反转程序。在运行时使用 calloc 分配内存时出现以下错误:

a.out: malloc.c:2372: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 *(sizeof(size_t))) - 1)) & ~((2 *(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long) old_end & pagemask) == 0)' failed.
Aborted (core dumped)

使用此代码:

int *temp = (int*)calloc(1, sizeof(int) * (l1+l2)) ;

虽然使用 malloc 而不是 calloc 可以正常工作。在谷歌搜索时,我发现这是一种内存损坏问题,但没有弄清楚

【问题讨论】:

  • 工作正常意味着您可以有效地使用temp
  • 在 C++ 中不要使用 calloc,在 C 中不要使用 don't cast the return
  • 关于您遇到的问题,因为您分配了零字节,malloccalloc 都允许返回 NULL 或有效指针(它的实现已定义)。如果你得到一个非空指针,所有对你“分配”的内存的写入都将超出范围,导致undefined behavior
  • 很抱歉是 1 而不是 0
  • calloc(0, sizeof(int) * (l1+l2)) 更改为calloc(1, sizeof(int) * (l1+l2)) 极大地改变了问题——不是吗?为什么你在通话中做乘法而不是让calloc() 为你做?不过,这是一个小问题。鉴于修改后的编码,您在某处践踏了界限。主要区别在于calloc() 将内存归零malloc() 不会。您可能会遇到将零点作为空指针并且工作方式不同的代码。 valgrind 是否适用于您的平台?如果是这样,请使用它。如果没有,请获取虚拟机。

标签: c++ c memory-management malloc calloc


【解决方案1】:
void* calloc(size_t num, size_t size);

这会分配一个块num 元素,每个元素的大小由size 给出。由于您将0 传递给num,因此您要求分配一个包含零元素的块。这肯定不是您想要的,因此,在某个地方,您会遇到错误。

我不确定您要做什么。看起来您正试图分配一个长度为l1+l2int 数组。在这种情况下你需要写:

int *temp = calloc(l1+l2, sizeof *temp);

请注意,我假设您正在编写 C,并且已从 calloc 中删除了返回值的强制转换。如果您正在编写 C++,那么您一开始就不会调用 calloc。你会使用std::vector<int>

【讨论】:

    【解决方案2】:

    您的calloc 调用对我来说似乎不太合理。您正在分配 个项目,每个项目的大小为 sizeof(int) * (l1+l2) 字节。

    话虽如此,我不确定断言是否真的有效。 calloc documentation 说:

    void *calloc(size_t nelem, size_t elsize);
    

    […]

    RETURN VALUE
    

    在成功完成nelemelsize 非零时,calloc() 应返回一个指针 到分配的空间。如果 nelemelsize 为 0,则为空指针或唯一 返回可以成功传递给free()的指针值。

    即通过这个描述,我希望你得到一个指针(可能是一个空指针),它不适合任何东西,但被传递给free()。也许实际上不是 calloc 调用本身失败了,而是后续代码尝试使用指针做某事?

    【讨论】:

    • 我很困惑,当您引用的手册明确表示您 可以 得到一个非空指针时,您期望来自 calloc(0, 0) 的空指针。关键是您不能通过返回的指针访问任何内存,因为它是空指针,或者因为它指向已分配内存的零字节。
    • 通过该描述,我期望“空指针或唯一指针值”。在后一种情况下,通过它写入很容易导致堆损坏。
    • 糟糕,我的想法超前于我的写作:事实上,我的意思是你可以返回一个空指针或一个你可以成功传递给@987654336的指针@ (但不取消引用,让我们通过它来写)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-09
    • 1970-01-01
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多