我有一个读取文件并为文件内容分配内存并将文件内容分配给指针然后返回指针的函数。然后我使用循环遍历字符串并使用指针算法打印每个字符。
我很确定我可以/应该使用 realloc 在每次迭代中重新分配更少的内存,而不是使用计数器跟踪迭代,但我不确定如何实现它。
所以在代码末尾,当我调用
free()
时,我从指针变量中减去计数器以释放 contents
指针最初指向的地址。
下面是我用来读取文件的代码以及我的循环所在的主要函数:
char *read_file(const char *filename) {
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
perror("Failed to open file");
exit(EXIT_FAILURE);
}
// Obtain information about the file
struct stat st;
if (fstat(fileno(fp), &st) != 0) {
perror("Failed to get file information");
exit(EXIT_FAILURE);
}
size_t file_size = st.st_size;
// Allocate a buffer to hold the contents of the file
char *buffer = (char *) malloc(file_size + 1);
if (buffer == NULL) {
perror("Failed to allocate memory");
exit(EXIT_FAILURE);
}
// Read the contents of the file into the buffer
size_t bytes_read = fread(buffer, 1, file_size, fp);
buffer[bytes_read] = '\0';
// Close the file and return the buffer
fclose(fp);
return buffer;
}
int main() {
char *contents = read_file("testNote.txt");
int counter = 0;
while (*contents != '\0') {
printf("%c", *contents);
++counter;
++contents;
}
free(contents - counter);
return 0;
}
据我所知,在实验之后这就是我想的那样,但我只是想确保我没有在这里做任何有害的事情
你所做的会奏效。每次你递增
contents
,你也递增counter
,所以contents - counter
给了你可以释放的原始指针。
当然,更好的方法是使用临时指针在分配的内存中递增,这样您就可以使用原始指针
free
.
int main() {
char *contents = read_file("testNote.txt");
char *tmp = contents;
while (*tmp != '\0') {
printf("%c", *tmp);
++tmp;
}
free(contents);
return 0;
}
不,这不安全。
假设您读取了一个大于 2147483647 字节或大约 2 GB 的文件。然后
counter
的值在您到达文件末尾时溢出,并且为负数。当你减去 contents - counter
时,你得到的地址与你从 malloc()
得到的地址不同。最好的情况是它崩溃了。最坏的情况是它破坏了堆并继续运行。
我建议使用@dbush 的建议。即使你能保证你不会得到 2GB 的文件,他们的代码仍然更容易推理。