英文:
Is this an acceptable way to deallocate memory in c?
问题
下面是您提供的代码的翻译部分:
// 我有一个函数,它读取一个文件并为文件内容分配内存,然后将文件内容分配给指针,然后返回指针。然后,我使用循环来遍历字符串,并使用指针算术打印每个字符。
// 我相当肯定我可以/应该在每次迭代时使用realloc来重新分配更少的内存,而不是使用计数器来跟踪迭代,但我不确定如何实现它。
// 因此,代替在代码末尾调用`free()`时,我从指针变量中减去计数器以释放最初指向的`contents`指针的地址。
// 以下是我用于读取文件的代码以及我的循环所在的主函数:
char *read_file(const char *filename) {
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
perror("无法打开文件");
exit(EXIT_FAILURE);
}
// 获取文件的信息
struct stat st;
if (fstat(fileno(fp), &st) != 0) {
perror("无法获取文件信息");
exit(EXIT_FAILURE);
}
size_t file_size = st.st_size;
// 分配一个缓冲区来保存文件的内容
char *buffer = (char *) malloc(file_size + 1);
if (buffer == NULL) {
perror("内存分配失败");
exit(EXIT_FAILURE);
}
// 将文件内容读取到缓冲区
size_t bytes_read = fread(buffer, 1, file_size, fp);
buffer[bytes_read] = '// 我有一个函数,它读取一个文件并为文件内容分配内存,然后将文件内容分配给指针,然后返回指针。然后,我使用循环来遍历字符串,并使用指针算术打印每个字符。
// 我相当肯定我可以/应该在每次迭代时使用realloc来重新分配更少的内存,而不是使用计数器来跟踪迭代,但我不确定如何实现它。
// 因此,代替在代码末尾调用`free()`时,我从指针变量中减去计数器以释放最初指向的`contents`指针的地址。
// 以下是我用于读取文件的代码以及我的循环所在的主函数:
char *read_file(const char *filename) {
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
perror("无法打开文件");
exit(EXIT_FAILURE);
}
// 获取文件的信息
struct stat st;
if (fstat(fileno(fp), &st) != 0) {
perror("无法获取文件信息");
exit(EXIT_FAILURE);
}
size_t file_size = st.st_size;
// 分配一个缓冲区来保存文件的内容
char *buffer = (char *) malloc(file_size + 1);
if (buffer == NULL) {
perror("内存分配失败");
exit(EXIT_FAILURE);
}
// 将文件内容读取到缓冲区
size_t bytes_read = fread(buffer, 1, file_size, fp);
buffer[bytes_read] = '\0';
// 关闭文件并返回缓冲区
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;
}
';
// 关闭文件并返回缓冲区
fclose(fp);
return buffer;
}
int main() {
char *contents = read_file("testNote.txt");
int counter = 0;
while (*contents != '// 我有一个函数,它读取一个文件并为文件内容分配内存,然后将文件内容分配给指针,然后返回指针。然后,我使用循环来遍历字符串,并使用指针算术打印每个字符。
// 我相当肯定我可以/应该在每次迭代时使用realloc来重新分配更少的内存,而不是使用计数器来跟踪迭代,但我不确定如何实现它。
// 因此,代替在代码末尾调用`free()`时,我从指针变量中减去计数器以释放最初指向的`contents`指针的地址。
// 以下是我用于读取文件的代码以及我的循环所在的主函数:
char *read_file(const char *filename) {
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
perror("无法打开文件");
exit(EXIT_FAILURE);
}
// 获取文件的信息
struct stat st;
if (fstat(fileno(fp), &st) != 0) {
perror("无法获取文件信息");
exit(EXIT_FAILURE);
}
size_t file_size = st.st_size;
// 分配一个缓冲区来保存文件的内容
char *buffer = (char *) malloc(file_size + 1);
if (buffer == NULL) {
perror("内存分配失败");
exit(EXIT_FAILURE);
}
// 将文件内容读取到缓冲区
size_t bytes_read = fread(buffer, 1, file_size, fp);
buffer[bytes_read] = '\0';
// 关闭文件并返回缓冲区
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;
}
') {
printf("%c", *contents);
++counter;
++contents;
}
free(contents - counter);
return 0;
}
希望这有助于您理解代码的工作原理。如果您有任何疑虑,请随时提出。
英文:
I have a function that reads a file and allocates memory for the files contents and assigns the files contents to a pointer and then returns the pointer. I then use a loop to loop over the string and print each character using pointer arithmetic.
I'm pretty sure I could/should use realloc to reallocate less memory each iteration as opposed to tracking the iterations with a counter but I'm not sure exactly how to implement it.
So instead at the end of the code when I call free()
I subtracted the counter from the pointer variable to deallocate the address that the contents
pointer originally pointed to.
Below is the code I used to read the file as well as the main function where my loop is at:
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;
}
As far as I can tell after experimenting this is working the way I'm thinking it is, but I just want to make sure I'm not doing anything harmful here
答案1
得分: 6
你正在做的方式有效。每次增加contents
时,也会增加counter
,因此contents - counter
给出了原始指针,可以进行释放。
当然,更好的方式是使用临时指针来遍历分配的内存,以便可以使用原始指针来进行free
。
int main() {
char *contents = read_file("testNote.txt");
char *tmp = contents;
while (*tmp != 'int main() {
char *contents = read_file("testNote.txt");
char *tmp = contents;
while (*tmp != '\0') {
printf("%c", *tmp);
++tmp;
}
free(contents);
return 0;
}
') {
printf("%c", *tmp);
++tmp;
}
free(contents);
return 0;
}
英文:
What you're doing will work. Each time you increment contents
, you also increment counter
, so contents - counter
gives you the original pointer that you can free.
Of course, a better way of doing this would be to use a temporary pointer to increment through the allocated memory so you can use the original to free
.
int main() {
char *contents = read_file("testNote.txt");
char *tmp = contents;
while (*tmp != 'int main() {
char *contents = read_file("testNote.txt");
char *tmp = contents;
while (*tmp != '\0') {
printf("%c", *tmp);
++tmp;
}
free(contents);
return 0;
}
') {
printf("%c", *tmp);
++tmp;
}
free(contents);
return 0;
}
答案2
得分: 1
不,这不安全。
假设您读取一个大于2147483647字节,约2GB的文件。然后,当您到达文件末尾时,counter
的值会溢出并变为负数。当您执行contents - counter
时,得到的地址与您从malloc()
获得的地址不同。最好的情况是程序崩溃,最糟糕的情况是它会损坏堆并继续运行。
我建议使用@dbush的建议。即使您可以保证不会遇到2GB的文件,他们的代码仍然更容易理解。
英文:
No, this isn't safe.
Suppose you read a file which is bigger than 2147483647 bytes, or about 2 GB. Then the value of counter
overflows by the time you get to the end of the file, and is negative. When you subtract contents - counter
, you get an address different from the one you got from malloc()
. The best case scenario is that it crashes. The worst case scenario is that it corrupts the heap and keeps running.
I would suggest using @dbush's suggestion. Even if you can guarantee you won't get 2GB files, their code is still easier to reason about.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论