C Realloc错误 - “Assertion`ptr == alloc_last_block'失败!”

问题描述:

我在C中写入一个函数,它接受一个链表和一个谓词,并返回一个包含满足此条件的链表的所有值的数组。这里的功能:C Realloc错误 - “Assertion`ptr == alloc_last_block'失败!”

void **get_all_that(list_t *l, int (*pred)(const void *)) { 
    void **vals = NULL; 
    int i = 0; // Number of matches found 
    const size_t vps = sizeof(void *); 
    node_t *n = l->first; 
    while (n) { 
     if (pred(n->value)) { 
      vals = (void **)realloc(vals, i*vps); // (*) 
      vals[i] = n->value; 
      i++; 
     } 
     n = n->next; 
    } 
    if (vals != NULL) { 
     vals = (void **)realloc(vals, i*vps); 
     vals[i] = NULL; // NULL-terminate array 
    } 
    return vals; 
} 

我在于始终返回1的谓词传递(即get_all_that基本上to_array),以及我的迭代,其中i = 4得到一个错误的加星号的线。回溯错误(从SIGABRT自动打印)是“*** glibc detected ***〜/ list/test:realloc():invalid next size:0x0804c0e8 ***”

我打开了GDB在i = 4时调用realloc之前告诉它打破。然后我尝试从GDB手动调用realloc(vals,i * vps),并得到错误消息:“由ld.so检测到的不一致:dl-minimal.c:138:realloc:声明`ptr == alloc_last_block'失败! ”

任何人都知道发生了什么事?

您的realloc正在分配一个元素太少。尝试用i+1代替i。在更换传递给它的指针之前,您还应该检查realloc的失败,否则在失败时将会发生内存泄漏(更不用说崩溃,因为您未能检查NULL),并从中删除不必要和丑陋的转换返回值realloc也不错。

+0

这样做。接得好。为什么这些演员阵容无效? – Nick 2010-10-05 03:26:31

+0

@Nick:因为'void *'隐式转换为任何其他指针类型(在C中;而不是在C++中)。 – caf 2010-10-05 03:52:02

+1

无效指针('malloc'和'realloc'返回)的整点是它们自动转换为任何(非函数)指针类型。为什么这是一个糟糕的主意(在风格,可维护性和掩盖错误方面)是一个您可以搜索的主题。 – 2010-10-05 03:53:58

而你的第一个realloc称为长度为0,这是一个free。所以建议把i+1加倍重要。

+0

这本身并不是一个问题,因为下一次调用会将由0调用返回的指针再次传递给'realloc'到'realloc'。无论大小为0的realloc是否返回NULL指针或有效的唯一指针(标准允许),程序将按预期工作。 – 2010-10-05 17:07:29

+0

还应该注意的是,GNU'malloc'在零尺寸分配时返回一个唯一的非空指针的行为使得它很难找到该错误,并且改变了本来很容易被捕获的空指针 - 将segfault解引用为一个轻度难以发现的内存腐败错误。 – 2010-10-05 17:08:43