【问题标题】:realloc: invalid next size errorrealloc: 无效的下一个大小错误
【发布时间】:2015-04-12 19:49:36
【问题描述】:

realloc 出现此错误,该错误仅出现在我学校的实验室计算机上,而不是我的。

在这个程序中,我将行号存储在 File_Node 结构中。 File_Node 是链表的一部分,每个节点都包含文件路径字符串和文件中的数组行号。

此程序运行良好,直到需要存储的行号过多 (> 3000)。

这是我的代码的相关部分:

           if ((token = strtok(NULL, delim)) != NULL) {
                    char *endptr = NULL;
                    int *linenum_tmp = NULL;
                    long line_number;
                    errno = 0;
                    line_number = strtol(token, &endptr, 10);

                    if (errno == ERANGE) {
                            exit_program("Integer overflow.");
                    }

                    if (*endptr != '\0' || endptr == token || line_number < 0) {
                            exit_program("Cannot parse line number input.");
                    }
                    if (tail->line_numbers == NULL) {
                            tail->line_numbers = malloc(num_array_sz * sizeof(int));
                    }
                    if (counter == num_array_sz) { //Area of interest
                            num_array_sz *= 2;
                            if ((linenum_tmp = realloc(tail->line_numbers, sizeof(int) * num_array_sz)) == NULL) { 
                                    exit_program("Error in realloc."); 
                            }
                    }
                    *(tail->line_numbers + counter - 1) = line_number;

            } else {
                    exit_program("Cannot parse line number input.");
            }
            counter++;

上面的代码是一个更大的while循环的一部分,它包含更多的行,但如果有必要我会发布它。这就是为什么底部有一个counter++。我基本上每次counter(代表存储的行数)达到num_array_sz,初始化为256时,都将num_array_sz的大小加倍。

在我自己的电脑上,我用比学校电脑更多的输入进行了测试,它运行完美。

我很好奇这是因为我学校的电脑内存有限,还是平台不同。

这是我在学校电脑上运行的 valgrind 输出:

==1579== Memcheck, a memory error detector
==1579== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==1579== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==1579== Command: ./rgpp_v2 -w the -b -n
==1579== 
==1579== Invalid write of size 4
==1579==    at 0x40110E: process_input (rgpp_v2.c:181)
==1579==    by 0x400DCC: main (rgpp_v2.c:103)
==1579==  Address 0x51e0b9c is 1,020 bytes inside a block of size 1,024 free'd
==1579==    at 0x4C29B7E: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==1579==    by 0x4010DD: process_input (rgpp_v2.c:177)
==1579==    by 0x400DCC: main (rgpp_v2.c:103)
==1579== 
==1579== Invalid free() / delete / delete[] / realloc()
==1579==    at 0x4C29B7E: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==1579==    by 0x4010DD: process_input (rgpp_v2.c:177)
==1579==    by 0x400DCC: main (rgpp_v2.c:103)
==1579==  Address 0x51e07a0 is 0 bytes inside a block of size 1,024 free'd
==1579==    at 0x4C29B7E: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==1579==    by 0x4010DD: process_input (rgpp_v2.c:177)
==1579==    by 0x400DCC: main (rgpp_v2.c:103)
==1579== 
Error in realloc.
==1579== 
==1579== HEAP SUMMARY:
==1579==     in use at exit: 3,477 bytes in 9 blocks
==1579==   total heap usage: 12 allocs, 3 frees, 8,717 bytes allocated
==1579== 
==1579== LEAK SUMMARY:
==1579==    definitely lost: 2,048 bytes in 1 blocks
==1579==    indirectly lost: 0 bytes in 0 blocks
==1579==      possibly lost: 0 bytes in 0 blocks
==1579==    still reachable: 1,429 bytes in 8 blocks
==1579==         suppressed: 0 bytes in 0 blocks
==1579== Rerun with --leak-check=full to see details of leaked memory
==1579== 
==1579== For counts of detected and suppressed errors, rerun with: -v
==1579== ERROR SUMMARY: 34 errors from 2 contexts (suppressed: 2 from 2)

这些错误指向realloc 行。

【问题讨论】:

  • 传递给函数 realloc 的第一个参数必须指向内存地址 0 (NULL),或者指向先前使用 mallocrealloc 分配的内存段。当您将tail-&gt;line_numbers 传递给realloc 时,您确定tail-&gt;line_numbers 确实指向这些选项之一吗?
  • @barakmanos 查看我的回答。导致问题的不是realloc;是他没有使用realloc返回的指针。

标签: c realloc


【解决方案1】:

你没有正确使用realloc

linenum_tmp = realloc(tail->line_numbers, ....
...
*(tail->line_numbers + counter - 1) = ...

如果realloc 需要重新分配你的内存,你传递给它的指针是freed。然后您继续使用tail-&gt;line_numbers旧的、已释放 值。

您必须始终使用realloc返回值

我想你想要的是:

tail->line_numbers = realloc(tail->line_numbers, ...

其次,您误解了valgrind 告诉您的内容。

==1579== Invalid write of size 4
==1579==    at 0x40110E: process_input (rgpp_v2.c:181)
==1579==    by 0x400DCC: main (rgpp_v2.c:103)
==1579==  Address 0x51e0b9c is 1,020 bytes inside a block of size 1,024 free'd
==1579==    at 0x4C29B7E: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==1579==    by 0x4010DD: process_input (rgpp_v2.c:177)
==1579==    by 0x400DCC: main (rgpp_v2.c:103)

它的意思是:在函数 process_inputrgpp_v2.c 的第 181 行)中,您正在访问以前为 freed 的内存。供您参考,它之前由realloc 释放,由process_inputrgpp_v2.c 的第177 行调用。

【讨论】:

  • 在 comp.lang.c 上,他们喜欢提出一个极端情况,即 realloc 失败(返回 NULL),但保留分配的原始数据。如果您只是覆盖变量,那么您已经丢失了数据。 (您是否可以在没有额外空间的情况下真正有效地恢复是另一个问题)。
  • 哇,谢谢。这就像一个魅力!我看过的例子使用了一个临时变量,所以我很困惑。原谅我可怕的无知,我正在查看 realloc 的手册页,它说 realloc 返回一个指向新分配内存的指针。所以我认为一个临时变量是必要的。
  • 不过,我肯定会注意@luserdroog 在他的评论中所说的话。要记住的一点是,如果realloc 返回一个非NULL 值,那么你传递给它的指针可能是freed,所以你不能再使用它了。您只是忘记将临时变量分配回第一个指针。
【解决方案2】:
            if (counter == num_array_sz) { //Area of interest
                    num_array_sz *= 2;
                    if ((linenum_tmp = realloc(tail->line_numbers, sizeof(int) * num_array_sz)) == NULL) { 
                            exit_program("Error in realloc."); 
                    }
            }
            *(tail->line_numbers + counter - 1) = line_number;

您需要使用来自realloc 的结果更新您的工作变量,如下所示:

            if (counter == num_array_sz) { //Area of interest
                    num_array_sz *= 2;
                    if ((linenum_tmp = realloc(tail->line_numbers, sizeof(int) * num_array_sz)) == NULL) { 
                            exit_program("Error in realloc."); 
                    }
            }

            tail->line_numbers = linenum_tmp; // <---!

            *(tail->line_numbers + counter - 1) = line_number;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-02
    • 2020-12-27
    • 2014-10-13
    • 2015-01-22
    • 1970-01-01
    • 2019-07-24
    相关资源
    最近更新 更多