2014-07-06 67 views
1

我是一个新的c,为了解它,我试图写一个函数来手动读取std输入的字符。该程序将从std读取行并输出它们,ant会在遇到空行时结束。双免费或腐败错误发生时,免费呼叫c

但是,如果输入流只包含三行或更少的行,它会工作正常,但如果输入包含4行以上,它总是会停止并显示错误。调用realloc和释放函数时发生错误:'double free或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; 
} 

的执行结果是:

[email protected]:~/vmshared$ ./mylib2 
abc 
def 
hij 

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

你为什么用C++标记它? –

+1

你的代码和问题类似于http://stackoverflow.com/questions/24592631/realloc-invalid-next-size-and-malloc-memory-corruption-fast/24592774 – deviantfan

+0

这个问题已经解决了这个问题:[ C - 如果使用realloc是免费的必需?](http://stackoverflow.com/questions/5426700/c-if-realloc-is-used-is-free-necessary) –

回答

1

因为你释放你的数据,然后使用它:

 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; 
} 

当然,真正realloc是一个复杂得多(因为它会检查当前块,看它是否可以扩展它分配新数据之前),并且可能不会定期致电malloc,但其功能大致如此。

原因存储比老指针不同变量的realloc的结果是它返回NULL的情况下 - 它不能扩展到新的大小 - 在这一点上,你需要一个temp和原指针,所以你不会泄漏旧指针的内存。

2

有你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的释放旧指针为您服务。
在您的主要功能中,您永远不会释放您的lines指针。

0

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

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

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

0

当您拨打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;,但它确实超出边际没有特别的伤害(没法比)减慢了程序的速度。

3

你的问题是在这里:

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

的情况下realloc成功了,你自由srealloc已释放它。 你可以看到这个answer了解更多详情。