我是c的新手,为了学习它,我正在尝试编写一个函数来手动读取std输入中的字符。程序将从std读取行并输出它们,当它遇到空行时它将结束。
但是,如果输入流只包含三行或更少行,则它可以正常工作,但如果输入包含4行以上,则它总是停止并显示错误。调用realloc和free函数时会发生错误:'双重释放或损坏(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 ***
答案 0 :(得分:3)
你的问题在这里:
temp = realloc(s, sizeof(char) * size);
if (s != NULL && temp != s) free(s);
如果realloc
成功,您可以在s
已经释放realloc
后免费{{1}}。
您可以查看此answer了解更多详情。
答案 1 :(得分:2)
您的readlines
和readline
功能存在问题。你的错误是由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
指针。
答案 2 :(得分: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;
}
当然,REAL realloc
要复杂得多(因为它检查当前块以查看它是否可以在分配新数据之前进行扩展),并且可能不会调用常规{{1} },但功能大致如此。
将malloc
的结果存储在与旧指针不同的变量中的原因是它返回realloc
的情况 - 它无法扩展到新的大小 - 此时,你需要一个NULL
和原始指针,所以你不要泄漏旧指针的内存。
答案 3 :(得分:0)
成功调用realloc后,不应释放原始内存区域。
temp = realloc(s, sizeof(char) * size);
if (s != NULL && temp != s) free(s); // This is wrong!
如果realloc移动您的数据,它也将释放旧区域。你自己不需要这样做。
答案 4 :(得分: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;
,但除了略微(无法估量地)减慢程序之外没有特别的伤害。