>我有一个文件,我想从中读取并将数据存储到一个字符数组中,我在每次读取字符后动态分配内存。我想动态地将内存完全分配给所需的大小。这是我所拥有的:
FILE *fp;
char *data;
int c=0;
fp=fopen("home/bob/Downloads/filename", "r");
data=malloc(sizeof(char));
do{
data[c]=fgetc(fp);
printf("data : %cn", data[c]);
c++;
data=realloc(data, sizeof(char)+c);
} while(data[c]!=EOF);
我遇到分段错误。
问题很可能在这里:
while(data[c]!=EOF)
请记住,您增加了循环内部的c
,因此data[c]
是您分配的内存的未初始化部分。这意味着只要未初始化的数据不(char) -1
,您就会继续逐个字符读取,这可能远远超出文件的实际结尾。
相反,请尝试这样的事情:
char *data = NULL;
size_t c = 0;
for (;;)
{
const int ch = fgets(fp);
if (ch == EOF)
break; /* Error or end of file */
char *tmp = realloc(data, c + 1);
if (tmp == NULL)
break; /* Could not allocate memory */
data = tmp;
data[c++] = ch;
}
当您的程序尝试评估以下条件时:
(data[c]!=EOF)
c
已递增,因此data[c]
尝试访问超出 data
数组范围的元素,从而导致未定义的行为。
首先,您必须使用带有 malloc coz malloc 返回 void* 的类型转换*
data=(char*)malloc(sizeof(char));
此外,EOF 不是字符 (EOF=-1)
while 循环中的条件指向内存中尚未初始化的部分。
int ch;
while(1)
{
if( (ch=fgets(fp))==EOF )
break;
data[c]=ch;
c++;
data=realloc(data, sizeof(char)+c);
}
do{
data[c]=fgetc(fp);
printf("data : %cn", data[c]);
c++;
data=realloc(data, sizeof(char)+c);
}while(data[c]!=EOF); // this should be the location of the seg fault
而 (data[c]) 查看数组末尾的后面。
做
}while(data[c - 1]!=EOF);
或在检查后递增 c
data[c]=fgetc(fp); --> This gives seg fault
因为你像这样递增c++
data=malloc(sizeof(char));
data
指向sizeof(char)
的记忆,当你做c++
然后data[c]
变成UB。
您已经分配了一个字节的内存。这绝对不足以读取文件。
我建议使用stat()
解释如何确定 C 中文件的大小? 获取大小,然后分配size*sizeof(char)
。
#include <sys/stat.h>
off_t fsize(const char *filename) {
struct stat st;
if (stat(filename, &st) == 0)
return st.st_size;
return -1;
}
{
FILE *fp;
char *data;
int c=0;
off_t size = fsize("home/bob/Downloads/filename") +1;
fp=fopen("home/bob/Downloads/filename", "r");
data=malloc(sizeof(char) * size);
do{
data[c]=fgetc(fp);
printf("data : %cn", data[c]);
c++;
data=realloc(data, sizeof(char)+c);
}while(data[c]!=EOF);
}