如何在不泄漏内存的情况下将 fgets() 读取的字符串存储在变量中?
How might I store in a variable the string read by fgets() without leaking memory?
我想要下面的代码来完成将它读取的文件的内容存储在一个变量中
content
没有泄漏内存:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
char* concat(const char *s1, const char *s2)
{
const size_t len1 = strlen(s1);
const size_t len2 = strlen(s2);
char *result = malloc(len1 + len2 + 1);
memcpy(result, s1, len1);
memcpy(result + len1, s2, len2 + 1);
return result;
}
int main() {
char path[] = "/home/jim/trackers_best.txt";
FILE *archivo = fopen(path,"r");
char line[200];
char * content = "";
if (archivo == NULL)
exit(1);
else {
fseek(archivo, 0L, SEEK_END);
int sz = ftell(archivo);
fseek(archivo, 0L, SEEK_SET);
if (sz < pow(10, 7) ) {
printf("\nThe content of %s is:\n", path);
while (feof(archivo) == 0) {
fgets(line, 200, archivo); //reads one line at a time - comment out the while loop to find out
content = concat(content, line);
//free(content);//No leaks but no content either
}
}
else {
puts("File take up more than 10 MBs, I refuse to read it.");
fclose(archivo);
exit(0);
}
}
fclose(archivo);
puts(content);
free(content);
return 0;
}
与使用 fread()
的代码非常相似:
#include<stdio.h>
#include<stdlib.h>
#include <math.h>
#include <sys/types.h>
int main() {
int count;
char path[] = "/home/jim/trackers_best.txt";
FILE *archivo = fopen(path,"rb");
if (archivo == NULL) {
puts("Does not exist.");
exit(1);
}
else {
fseek(archivo, 0L, SEEK_END);
int sz = ftell(archivo);
char contenido[sz];
fseek(archivo, 0L, SEEK_SET);
if (sz < pow(10, 7) ) {
count = fread(&contenido, 10 * sizeof(char), sz, archivo);//reads 10 characters at a time.
}
else {
puts("File take up more than 10 MBs, I refuse to read it.");
}
fclose(archivo);
// Printing data to check validity
printf("Data read from file: %s \n", contenido);
printf("Elements read: %i, read %li byte at a time.\n", count, 10 * sizeof(char));
}
return 0;
}
第一个代码片段泄漏了内存,valgrind 证明了这一点:
...
total heap usage: 44 allocs, 4 frees, 23,614 bytes allocated
...
==404853== LEAK SUMMARY:
==404853== definitely lost: 17,198 bytes in 40 blocks
...
当我试图通过在 while 循环中执行 free()
来防止此类泄漏时,我没有在 content
中存储任何值。如何在不泄漏内存的情况下存储 fgets
读取的字符串?
您知道自己需要做什么,但没有做对
content = concat(content, line);
//free(content);//No leaks but no content either
您需要保留旧内容指针,以便在创建新内容指针后将其删除
char *oldc = content;
content = concat(content, line);
free(oldc);
当您在 second 次调用 concat
时,first 调用的值被 malloc
打电话。那就是内存泄漏。
我假设您希望 content
是一个长字符串,其中包含来自 所有 行的数据。
您想在 concat
中使用 realloc
(对比 malloc
),只需将 s2
附加到放大的 s1
.
使用此修改后的方案,而不是 char *content = "";
,您需要:char *content = NULL;
此外,不要使用 feof
而且,ftell
returns long
和 不是 int
。而且,最好不要使用pow
与极限进行比较。
这里是重构后的代码(我已经编译了但是没有测试过):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
char *
concat(char *s1, const char *s2)
{
size_t len1;
size_t len2;
if (s1 != NULL)
len1 = strlen(s1);
else
len1 = 0;
len2 = strlen(s2);
s1 = realloc(s1,len1 + len2 + 1);
if (s1 == NULL) {
perror("realloc");
exit(1);
}
memcpy(s1 + len1, s2, len2 + 1);
return s1;
}
int
main(void)
{
char path[] = "/home/jim/trackers_best.txt";
FILE *archivo = fopen(path, "r");
char line[200];
#if 0
char *content = "";
#else
char *content = NULL;
#endif
if (archivo == NULL)
exit(1);
fseek(archivo, 0L, SEEK_END);
long sz = ftell(archivo);
fseek(archivo, 0L, SEEK_SET);
if (sz < (10 * 1024 * 1024)) {
printf("\nThe content of %s is:\n", path);
while (fgets(line, sizeof(line), archivo) != NULL)
content = concat(content, line);
}
else {
puts("File take up more than 10 MBs, I refuse to read it.");
fclose(archivo);
exit(0);
}
fclose(archivo);
if (content != NULL)
puts(content);
free(content);
return 0;
}
我想要下面的代码来完成将它读取的文件的内容存储在一个变量中
content
没有泄漏内存:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
char* concat(const char *s1, const char *s2)
{
const size_t len1 = strlen(s1);
const size_t len2 = strlen(s2);
char *result = malloc(len1 + len2 + 1);
memcpy(result, s1, len1);
memcpy(result + len1, s2, len2 + 1);
return result;
}
int main() {
char path[] = "/home/jim/trackers_best.txt";
FILE *archivo = fopen(path,"r");
char line[200];
char * content = "";
if (archivo == NULL)
exit(1);
else {
fseek(archivo, 0L, SEEK_END);
int sz = ftell(archivo);
fseek(archivo, 0L, SEEK_SET);
if (sz < pow(10, 7) ) {
printf("\nThe content of %s is:\n", path);
while (feof(archivo) == 0) {
fgets(line, 200, archivo); //reads one line at a time - comment out the while loop to find out
content = concat(content, line);
//free(content);//No leaks but no content either
}
}
else {
puts("File take up more than 10 MBs, I refuse to read it.");
fclose(archivo);
exit(0);
}
}
fclose(archivo);
puts(content);
free(content);
return 0;
}
与使用 fread()
的代码非常相似:
#include<stdio.h>
#include<stdlib.h>
#include <math.h>
#include <sys/types.h>
int main() {
int count;
char path[] = "/home/jim/trackers_best.txt";
FILE *archivo = fopen(path,"rb");
if (archivo == NULL) {
puts("Does not exist.");
exit(1);
}
else {
fseek(archivo, 0L, SEEK_END);
int sz = ftell(archivo);
char contenido[sz];
fseek(archivo, 0L, SEEK_SET);
if (sz < pow(10, 7) ) {
count = fread(&contenido, 10 * sizeof(char), sz, archivo);//reads 10 characters at a time.
}
else {
puts("File take up more than 10 MBs, I refuse to read it.");
}
fclose(archivo);
// Printing data to check validity
printf("Data read from file: %s \n", contenido);
printf("Elements read: %i, read %li byte at a time.\n", count, 10 * sizeof(char));
}
return 0;
}
第一个代码片段泄漏了内存,valgrind 证明了这一点:
...
total heap usage: 44 allocs, 4 frees, 23,614 bytes allocated
...
==404853== LEAK SUMMARY:
==404853== definitely lost: 17,198 bytes in 40 blocks
...
当我试图通过在 while 循环中执行 free()
来防止此类泄漏时,我没有在 content
中存储任何值。如何在不泄漏内存的情况下存储 fgets
读取的字符串?
您知道自己需要做什么,但没有做对
content = concat(content, line);
//free(content);//No leaks but no content either
您需要保留旧内容指针,以便在创建新内容指针后将其删除
char *oldc = content;
content = concat(content, line);
free(oldc);
当您在 second 次调用 concat
时,first 调用的值被 malloc
打电话。那就是内存泄漏。
我假设您希望 content
是一个长字符串,其中包含来自 所有 行的数据。
您想在 concat
中使用 realloc
(对比 malloc
),只需将 s2
附加到放大的 s1
.
使用此修改后的方案,而不是 char *content = "";
,您需要:char *content = NULL;
此外,不要使用 feof
而且,ftell
returns long
和 不是 int
。而且,最好不要使用pow
与极限进行比较。
这里是重构后的代码(我已经编译了但是没有测试过):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
char *
concat(char *s1, const char *s2)
{
size_t len1;
size_t len2;
if (s1 != NULL)
len1 = strlen(s1);
else
len1 = 0;
len2 = strlen(s2);
s1 = realloc(s1,len1 + len2 + 1);
if (s1 == NULL) {
perror("realloc");
exit(1);
}
memcpy(s1 + len1, s2, len2 + 1);
return s1;
}
int
main(void)
{
char path[] = "/home/jim/trackers_best.txt";
FILE *archivo = fopen(path, "r");
char line[200];
#if 0
char *content = "";
#else
char *content = NULL;
#endif
if (archivo == NULL)
exit(1);
fseek(archivo, 0L, SEEK_END);
long sz = ftell(archivo);
fseek(archivo, 0L, SEEK_SET);
if (sz < (10 * 1024 * 1024)) {
printf("\nThe content of %s is:\n", path);
while (fgets(line, sizeof(line), archivo) != NULL)
content = concat(content, line);
}
else {
puts("File take up more than 10 MBs, I refuse to read it.");
fclose(archivo);
exit(0);
}
fclose(archivo);
if (content != NULL)
puts(content);
free(content);
return 0;
}