我有一个我无法弄清楚的问题。我有以下文件:file_reader.c, file_reader.h, file_writer.c, file_writer.h, test_file_reader.c
我正在使用' struct'读写文件。为了更好地理解,我编写了以下代码test_file_reader.c
:
#include <stdio.h>
#include "file_reader.h"
#include "file_writer.h"
int main ()
{
char *file_path = "/home/freitas/Dropbox/projects/gcleaner/cleaners/custom.xml";
struct FileReader *fr = malloc(sizeof(struct FileReader));
file_reader_new (file_path, fr);
show_file_reader_values(fr);
struct FileWriter *fw = malloc(sizeof(struct FileWriter));
fw->file_path = "/tmp/text1.txt";
fw->content = "aaa";
write (fw);
show_file_reader_values(fr);
return 0;
}
void show_file_reader_values(const struct FileReader *fr)
{
printf("==========FILE READER==========\n");
printf("file path: %s\n", fr->file_path);
printf("----------file content---------\n");
printf("content:\n%s\n", fr->content);
printf("----------file content---------\n");
printf("n lines: %d\n", fr->n_lines);
printf("n characters: %d\n", fr->n_characters);
printf("==========FILE READER==========\n\n");
}
函数&#39; file_reader_new&#39;读取文件,然后将内容,文件路径,行数和字符数签名到&#39; struct&#39; &#39;的FileReader&#39;
当我调用函数&#39; show_file_reader_values&#39;在第一次我没有内容问题,但当我打电话给函数&#39;写&#39;然后调用函数&#39; show_file_reader_values&#39;再一次,内容不再相同了。问题是功能“写”&#39;文件&#39; file_writer.c&#39;并且它的结构与文件&#39; file_reader&#39;没有任何关系。和它的结构。那么,使用另一个struct的函数如何改变另一个文件的另一个结构的值?
输出:
[freitas@localhost test]$ ./test_file_reader
==========FILE READER==========
file path: /home/freitas/Dropbox/projects/gcleaner/cleaners/custom.xml
----------file content---------
content:
<cleaner> <id>k3b</id> <label>k3b</label> <description>Disc writing software</description> <option> <id>log</id> <label>Log</label> <description>Delete the log file which contains information about the last writing session(s).</description> <command>delete</command> <search>glob</search> <path>~/.kde/share/apps/k3b/*.log</path> </option> <option> <id>log2</id> <label>Log</label> <description>Delete the log file which contains information about the last writing session(s).</description> <command>delete</command> <search>glob</search> <path>~/.kde/share/apps/k3b/*.log</path> </option> </cleaner>
----------file content---------
n lines: 1
n characters: 621
==========FILE READER==========
==========FILE READER==========
file path: /home/freitas/Dropbox/projects/gcleaner/cleaners/custom.xml
----------file content---------
content:
<cleaner> <id>k��U�N
----------file content---------
n lines: 1
n characters: 621
==========FILE READER==========
你知道吗?在第一次通话中,我得到了整个输出:
<cleaner> <id>k3b</id> <label>k3b</label> <description>Disc wri...
但在第二次通话中我有:
<cleaner> <id>k��U�N
file_reader.c
#include <stdio.h>
#include <stdlib.h>
#include "file_reader.h"
int file_reader_new(const char *file_path, struct FileReader *fr)
{
char *content; // holds the file content.
int counter; // holds the file number of lines.
size_t i; // indexing into content.
size_t buffer_size; // size of the content.
char *temp; // for realloc().
char c; // for reading from the input.
FILE *input; // our input stream.
if ((input = fopen(file_path, "r")) == NULL) {
fprintf(stderr, "Error opening input file %s\n", file_path);
exit(EXIT_FAILURE);
}
/* Initial allocation of content */
counter = 0;
i = 0;
buffer_size = BUFSIZ;
if ((content = malloc(buffer_size)) == NULL) {
fprintf(stderr, "Error allocating memory (before reading file).\n");
fclose(input);
}
while ((c = fgetc(input)) != EOF) {
/* Enlarge content if necessary. */
if (i == buffer_size) {
buffer_size += BUFSIZ;
if ((temp = realloc(content, buffer_size)) == NULL) {
fprintf(stderr, "Ran out of core while reading file.\n");
fclose(input);
free(content);
exit(EXIT_FAILURE);
}
content = temp;
}
/* Add input char to the content. */
content[i++] = c;
/* If the character is a break of line
* then the counter will be incremented.
*/
if (c == '\n')
counter++;
}
/* Test if loop terminated from error. */
if (ferror(input)) {
fprintf(stderr, "There was a file input error.\n");
free(content);
fclose(input);
exit(EXIT_FAILURE);
}
/* Make the content a bona-fide string. */
if (i == buffer_size) {
buffer_size += 1;
if ((temp = realloc(content, buffer_size)) == NULL) {
fprintf(stderr, "Ran out of core (and only needed one more byte too ;_;).\n");
fclose(input);
free(content);
exit(EXIT_FAILURE);
}
content = temp;
}
content[i] = '\0';
/* Assigns the variables to the corresponding
* element of the struct.
*/
fr->file_path = file_path;
fr->content = content;
fr->n_lines = counter;
fr->n_characters = i;
/* Clean up. */
free(content);
fclose(input);
return 0;
}
file_reader.h
#ifndef FILE_READER_H_
#define FILE_READER_H_
typedef struct FileReader
{
char *content; // holds the file content.
char *file_path; // holds the file path.
int *n_lines; // holds the number of lines.
int *n_characters; // holds the number of characters.
} FileReader;
// file_reader_new - reads the file
int file_reader_new(const char *file_path, struct FileReader *fr);
#endif
file_writer.c
#include <stdio.h>
#include "file_writer.h"
void write (struct FileWriter *fw)
{
FILE *f = fopen(fw->file_path, "w");
if (f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
fprintf(f, "%s", fw->content);
fclose(f);
}
file_writer.h
#ifndef FILE_WRITER_H_
#define FILE_WRITER_H_
typedef struct FileWriter
{
char *file_path;
char *content;
int *error;
} FileWriter;
#endif
你能帮帮我吗?谢谢!
答案 0 :(得分:1)
struct FileReader *fr = malloc(sizeof(struct FileReader));
没有必要这样做。所有你需要的是:
struct FileReader fr;
同样在这里:
struct FileWriter fw;
然后只需将这些变量的地址传递给必需的函数。
请注意,这不作为答案提供给您,仅作为注释来清除您的代码以删除对堆的无关调用。碰巧真正的问题存在于其他地方,你在这里看到的是undefined behavior
充满荣耀。
答案 1 :(得分:1)
我不确定你是如何从文件,字符或块中读取的,但无论如何,
因为您更新content
缓冲区中的读取数据,并将content
缓冲区内file_reader_new()
的地址存储到变量fr->content
中并立即释放内存将最终失去你读过的数据。并导致称为悬空指针
悬空指针
(指针变量,指向已释放的内存)
这就是为什么总是建议在释放到NULL
之后设置指针变量。在某些情况下,取消引用悬空指针会导致Segmentation fault
或undefined behavior
。
此外,由于struct
的所有成员变量都是指针,因此最好将它们初始化为NULL
。
如果您要进行动态分配,可以使用calloc
初始化struct
中的所有变量,而不是malloc
将所有成员初始化为NULL
。也适用于string
。
答案 2 :(得分:0)
我看到这是一个问题:
fr->content = content;
fr->n_lines = counter;
fr->n_characters = i;
/* Clean up. */
free(content); /* <-- Danger */
您可以在file_reader_new
功能中执行此操作。然后,您拨打show_file_reader_values
并在该功能中访问content
:
printf("content:\n%s\n", fr->content);
由于您在内容上调用free()
,该指针不再指向有效内存,因此会发生未定义的行为。
修复方法是在fr
上为内容分配空间,并将content
的字符复制到此空间,或者只是不在free
上调用content
。
所以要么这样做:
fr->content = malloc(i + 1);
strcpy(fr->content, content);
fr->n_lines = counter;
fr->n_characters = i;
/* Clean up. */
free(content);
或者这个:
fr->content = content;
fr->n_lines = counter;
fr->n_characters = i;
/* No call to free(content) done */