【问题标题】:double free or corruption error happens when call free in c在 c 中调用 free 时发生双重释放或损坏错误
【发布时间】:2014-08-26 22:17:16
【问题描述】:

我是 c 的新手,为了学习它,我正在尝试编写一个函数来手动从标准输入中读取字符。程序会从std中读取行并输出,遇到空行就结束。

但是如果输入流只包含 3 行或更少的行,它工作得很好,但如果输入包含 4 行以上,它总是会因错误而停止。调用 realloc 和 free 函数时出现错误:'double free or corruption (fasttop): 0x0000000001f46030 *',为什么?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *readline(int *length) {
    char ch, *s = NULL, *temp = NULL;
    int UNIT = 3, size = 0, index = 0;
    while ((ch = getchar()) != EOF) {
        if (size == 0 || index >= size) {
            size += UNIT;
            temp = realloc(s, sizeof(char) * size);
            if (s != NULL && temp != s) free(s);
            s = temp;
            temp = NULL;
        }

        s[index++] = (ch == '\n') ? '\0' : ch;
        if (ch == '\n') break;
    }
    *length = index - 1;
    return s;
}

char **readlines(int *count) {
    char **lines = NULL, **tempLines = NULL;
    int UNIT = 1, size = 0, index = 0;
    int length = 0;
    char *line = NULL;
    while ((line = readline(&length)) != NULL) {
        if (strlen(line) == 0) break;
        if (size == 0 || index >= size) {
            size += UNIT;
            tempLines = realloc(lines, size * sizeof(char *));
            if (lines != NULL && tempLines != lines) free(lines);
            lines = tempLines;
            tempLines = NULL;
        }
        lines[index++] = line;
    }
    *count = index;
    return lines;
}

int main(int argc, char *argv[]) {
    int length = 0, index = 0;
    char **lines = readlines(&length);
    printf("The lines you typed are: \n");
    for (; index < length; index++) {
        printf("%5s %s.\n", "-", lines[index]);
    }
    return 0;
}

执行结果为:

xxx@xxx:~/vmshared$ ./mylib2
abc
def
hij

The lines you typed are: 
    - abc.
    - def.
    - hij.
xxx@xxx:~/vmshared$ ./mylib2
11
22
33
44
*** Error in `./mylib2': double free or corruption (fasttop): 0x00000000017f1030 ***

【问题讨论】:

  • 你为什么把它标记为 C++?
  • 你的代码和问题类似于stackoverflow.com/questions/24592631/…
  • 这个问题已经解决了这个问题:C - If realloc is used is free necessary?
  • 关于这一行:if (s != NULL && temp != s) free(s);,函数 realloc 在复制 old are 的内容后释放 old area,除非返回的指针与原始指针相同(通常但并非总是更改。)因此,当新区域与旧区域不同时,您在 realloc 函数已释放的区域上调用 free(s)。

标签: c free realloc


【解决方案1】:

您的 readlinesreadline 函数有问题。您的错误是由 realloc 调用后释放指针引起的。

tempLines = realloc(lines, size * sizeof(char *));
if (lines != NULL && tempLines != lines) free(lines);  // wrong

temp = realloc(s, sizeof(char) * size);
if (s != NULL && temp != s) free(s);  //wrong

如果内存内容被移动到另一个位置,realloc 会为您释放旧指针。
在你的 main 函数中,你永远不会释放你的 lines 指针。

【讨论】:

    【解决方案2】:

    您应该在成功调用 realloc 后释放原始内存区域。

    temp = realloc(s, sizeof(char) * size);
    if (s != NULL && temp != s) free(s); // This is wrong!
    

    如果 realloc 移动您的数据,它也会释放旧区域。你不需要自己做。

    【讨论】:

      【解决方案3】:

      你的问题在这里:

       temp = realloc(s, sizeof(char) * size);
       if (s != NULL && temp != s) free(s);
      

      如果realloc 成功,您在realloc 已经释放它之后释放s。 您可以查看此answer 了解更多详情。

      【讨论】:

        【解决方案4】:

        因为您正在释放数据然后使用它:

                temp = realloc(s, sizeof(char) * size);
                if (s != NULL && temp != s) free(s);
        

        这意味着您正在写入已释放的内存 - 这很糟糕。

        函数realloc可以看做是:

        void *realloc(void *ptr, size_t new_size)
        {
            void* newptr = malloc(size);
            size_t oldsize = find_size(ptr);
            memcpy(newptr, ptr, oldsize);
            free(ptr);
            return newptr;
        }
        

        当然,REAL realloc 要复杂得多(因为它会在分配新数据之前检查当前块是否可以扩展),并且可能不会调用常规的 malloc,但是功能大致是这样的。

        realloc 的结果存储在与旧指针不同的变量中的原因是它返回NULL - 它无法扩展到新大小 - 此时,您需要一个@ 987654328@ 和原始指针,这样就不会泄漏旧指针的内存。

        【讨论】:

          【解决方案5】:

          当你调用realloc()并且成功时,旧的内存位置已经被释放,新的位置被返回。新旧位置有可能相同。但是,无论哪种方式,释放旧指针都是不正确的。立即释放新指针会很古怪。

          因此,这段代码不正确:

          temp = realloc(s, sizeof(char) * size);
          if (s != NULL && temp != s)
              free(s);
          s = temp;
          temp = NULL;
          

          应该是这样的:

          temp = realloc(s, size);
          if (temp == NULL)
              …report error and exit function…
          s = temp;
          

          没有必要在赋值后设置temp = NULL;,尽管它除了稍微(不可估量地)减慢程序速度之外并没有特别的危害。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-03-12
            • 1970-01-01
            • 1970-01-01
            • 2013-12-04
            • 1970-01-01
            • 2013-05-10
            相关资源
            最近更新 更多