我对这段我修改了很多次的代码有问题(但错误总是出现(:似乎在释放"过滤器"的最后一个索引时出错
char** read_and_filter(int fd) {
char buf[MAXLENGTH];
char **bufs=NULL;
char ch;
int j = 0, len = 0, t = 0;
while (!t && read(fd,&ch,1) == 1) {
switch (ch) {
case 'n':
t = 1;
case ' ':
bufs = realloc(bufs, (j+1)*sizeof(char*));
bufs[j++] = strndup(buf,len);
memset(buf,0,len);
len = 0;
break;
default:
buf[len++] = ch;
}
}
bufs[j] = 0;
return bufs;
}
int main(int argc, char **argv) {
char **filter;
int i,fd = open("input.txt",O_RDONLY);
filter = read_and_filter(fd);
for(i = 0; filter[i]; i++) {
printf("%sn",filter[i]);
free(filter[i]);
}
return 0;
}
这是输出:
0x1521030
HOME
0x1521050
2
0x1521070
A
0x1521010
8
0x15210c0
D
*** Error in `./test': free(): invalid pointer: 0x00000000015210c0 ***
我还尝试使用 valgrind 调试它(它告诉我分配器试图释放 9 字节,而字符总和为 8,奇怪不是吗?(和 gdb,但没有任何效果。输入的第一行.txt是"HOME 2 A 8 D">
第一次执行这些行时
bufs = realloc(bufs, (j+1)*sizeof(char*));
bufs[j++] = strndup(buf,len);
获取 1 个指针的内存(j 为 0(。这不会为您在函数末尾编写的结束NULL
留下空间
bufs[j] = 0;
因此,您正在超出分配的内存进行写入,因此具有未定义的行为。同样,每次扩展缓冲区长度时。
read_and_filter
结束时的bufs[j] = 0;
写入未分配的内存。你从来没有realloc
过你的bufs
,因为那额外的0
.
内存泄漏发生在两个地方 - strdup 和 realloc
一个答案是使用 malloc 为 main 中的缓冲区进行初始内存分配,然后将指向已分配内存的指针传递给函数。然后,该函数可以重新分配缓冲区,并将数据复制到其中。
从函数返回时,main 可以直接从缓冲区访问数据,因为它有一个指向它的有效指针,然后可以在关闭之前释放该内存。
根据瓦尔格林德的说法,以下没有记忆丧失。
void read_and_filter(int fd, char **bufs) {
char buf[100];
char ch;
int j = 0, len = 0, t = 0;
while (!t && read(fd,&ch,1) == 1) {
switch (ch) {
case 'n':
t = 1;
case ' ':
*bufs = realloc(*bufs, (j + 2)*sizeof(char*));
strncpy(bufs[j++], buf, len);
memset(buf,0,len);
len = 0;
break;
default:
buf[len++] = ch;
}
}
bufs[j] = 0;
return;
}
int main(int argc, char **argv) {
char *bptr = malloc(1);
int fd = open("input.txt", O_RDONLY);
read_and_filter(fd, &bptr);
printf("%sn", bptr);
free(bptr);
return 0;
但是,我不能确定这是否完全复制了OP的预期功能,但是整体方法确实可以解决内存问题。