我正在编写一个程序以打印出任何大于3的行输入。
它适用于一些相当长的输入行,但是对于太长的字符串,我收到了内存损坏的错误消息
*** Error in `./print-80': malloc(): memory corruption (fast): 0x00000000022ff030 ***
我不知道错误是从哪里来的。谁能解释我为什么存在错误以及如何解决该错误? 下面是程序
#include <stdio.h>
#include <stdlib.h>
#define LIMIT 3
#define LEAST_LENGTH 3
//function prototype
void copy(char* from, char* to);
int getline(char* s, int capacity);
int increase_capacity(char* s, int capacity);
int main(void)
{
int length, i;
char* line = calloc(LIMIT, sizeof(char));
while ((length = getline(line, LIMIT)) > 0)
{
if (length > LEAST_LENGTH)
printf("Output: %s\n", line);
//reset the line
for (i = 0; i < length; i++)
*(line + i) = 0;
}
free(line);
return 0;
}
int getline(char* line, int capacity)
{
int c, length;
length = 0;
while ((c = getchar()) != EOF && c != '\n')
{
if (length > (capacity - 1))
{
capacity = increase_capacity(line, capacity);
printf("Address of line after increasing cap: %p\n", line);
}
line[length++] = c;
}
if (c == '\n')
line[length++] = '\0';
return length;
}
int increase_capacity(char* s, int capacity)
{
int i;
capacity *= 2;
char *new_s = calloc(capacity, sizeof(char));
copy(s, new_s);
s = new_s;
free(new_s);
return capacity;
}
void copy(char* from, char* to)
{
int i = 0;
while ((to[i] = from[i]) != '\0')
++i;
}
答案 0 :(得分:2)
您的increase_capacity
函数可以更改存储数据的地址。但是它不会将此信息返回给其调用方。因此getline
将写入旧的缓冲区地址。同样,main
无法获得新地址,因此它将访问旧地址和free
一个可能已经释放的块。
此外,您的increase_capacity
函数分配内存来保存数据,然后释放该内存。这样就没有地方保存数据了!
int increase_capacity(char* s, int capacity)
{
int i;
capacity *= 2;
char *new_s = calloc(capacity, sizeof(char)); // allocate a larger block
copy(s, new_s); // copy the data into the larger block
s = new_s; // stash a pointer to the larger block in a local
free(new_s); // free the block?!
return capacity;
}
因此,我们分配一个新块,将数据复制到其中,然后释放它。那是没有道理的,我们需要保留更大的块,因为这是增加容量的功能的全部要点。我们也不会返回新块的地址,因此,即使我们不释放它,也没有其他代码可以访问它,而我们最终会泄漏它。哎呀。
我建议您创建一个struct
,它同时包含指向块的指针及其大小。将指向该struct
的指针传递给类似increase_capacity
的函数,以便它可以修改指针和结构的大小,并且调用者可以看到更改。