简体   繁体   English

在C中读取二进制文件时出现分段错误

[英]Segmentation fault while reading binary file in C

Im a beginner in C. I would like to write and read a binary file , and i reached this so far: 我是C语言的初学者。我想写和读一个二进制文件 ,到目前为止,我达到了:

I can my struct to a binary file, and can read. 我可以将结构体转换为二进制文件,并且可以读取。

Problem one: I can only read integers, somehow strings are printed as garbage or random characters. 问题一:我只能读取整数,以某种方式将字符串打印为垃圾或随机字符。

Problem two: If i run my program, i add some entries to my binary file, then i print all the entries it is working fine (except Problem one), but after i terminate my program and run AGAIN i got Segmentation Fault while i try to read the file. 问题二:如果我运行程序,则将一些条目添加到二进制文件中,然后我将所有条目打印正常(问题一除外),但是在我终止程序并再次运行后,我尝试时遇到了分段错误读取文件。

Please help me, i just cannot move forward. 请帮助我,我只是无法前进。

/* Our structure */
struct rec
{
    int max,cost;
    char *name;
};


struct rec addNewEntry()
{

    //init
    char name[256];
    int max;
    int cost;

    //input
    printf("Type name: \n");
    scanf("%s" , &name) ;

    printf("Type guests limit: \n");
    scanf("%d", &max);

    printf("Type price: \n");
    scanf("%d", &cost);

    //create record
    struct rec record;

    record.name = name;
    record.max = max;
    record.cost = cost;

    return record;

}

int main()
{

    FILE *ptr_myfile;


    //////////////////////////MENU////////////////////////////////

    int option=-1;


    while(option!=3)
    {

        printf("\n=== MENU === \n");
        printf("\n1. Print all entries");
        printf("\n2. Add new entry");
        printf("\n3. Exit");
        printf("\n");

        printf("\nType menu option:");

        scanf("%d", &option);


        if(option == 1)
        {
            printf("\n...Printing all entries\n");



            int f=open("stadionok.db",O_RDONLY); 
            if (f<0){ perror("Error at opening the file\n");exit(1);}

             struct rec my_record; 

             while (read(f,&my_record,sizeof(my_record))){ //use write for writing
                printf("name: %s  \n",my_record.name);
                printf("max: %d  \n",my_record.max);
                printf("cost: %d  \n",my_record.cost);
             } 


            close(f);


        }
        else if(option ==2)
        {

            printf("\n...Type a new entry\n");


            //OPEN AND CHECK
            ptr_myfile=fopen("stadionok.db","a");
            if (!ptr_myfile)
            {
                printf("Unable to open file!");
                return 1;
            }

            //TYPE A NEW ENTRY
            struct rec new_stad = addNewEntry();

            //WRITE TO FILE
            fwrite(&new_stad, sizeof(struct rec), 1, ptr_myfile);


            //CLOSE
            fclose(ptr_myfile);

            printf("Done.\n");
        }


    }   




    return 0;
}

EDIT: 编辑:

I modified just as you suggested and now i got: error: incompatible types in assignment 我按照您的建议进行了修改,现在我得到: 错误:分配中的类型不兼容

at: 在:

char name[256];


//input
printf("Type name: \n");
scanf("%s" , &name) ;


struct rec record;

record.name = name; //HERE

The reason you get garbage strings is that you are writing a char pointer into the file. 您获得垃圾字符串的原因是您正在将char 指针写入文件。 The simple way to do what you want is to use a char array with a fixed length inside your struct. 执行所需操作的简单方法是在结构内部使用固定长度的char数组。 like so: 像这样:

struct rec
{
    int max,cost;
    char name[1024];
};

It is also the reason for the crash. 这也是坠机的原因。 When you read the data and trying to print the string the printf() probably tries to read from a memory block that is not valid, because the memory addresses changed. 当您读取数据并尝试打印字符串时, printf()可能会尝试从无效的内存块中读取数据,因为内存地址已更改。

If you want to write strings with dynamic size into the file it gets a bit more complicated. 如果要将动态大小的字符串写到文件中,它将变得更加复杂。
Then you should not write the struct itself, but the values of it and the size of the string. 然后,您不应该编写该结构本身,而应该编写它的值和字符串的大小。
PseudoCode Example: 伪代码示例:

write(max);
write(cost);
write(strlen(name)); // strlen + 1 if you want to include \0
write(name);

max = readInt();
cost = readInt();
nameLen = readInt();
allocatememory(nameLen);
name = read_n_bytes(namelen);


To your edit: if rec.name is still a pointer (char*) you have to assign a pointer to it, not an array. 编辑:如果rec.name仍然是指针(char *),则必须为其分配一个指针,而不是数组。

rec.name = &name;

if your rec.name is an array with a fixed size now: 如果您的rec.name现在是具有固定大小的数组:

strncpy(rec.name, name, sizeof(rec.name)); // copy the string to rec.name
rec.name[strlen(name)] = '\0'; // add a binary 0 to the end of the string

Note: if you are reading more than 1 struct (in a loop), you should not use char name[256]; 注意:如果您要读取1个以上的结构(在循环中),则不应使用char name[256]; , because every rec.name would be pointing to name which is overwritten everytime you read a new value. ,因为每个rec.name都指向每次读取新值时都会被覆盖的name。 Use the following construct for every entry: 对每个条目使用以下构造:

char* name; //define name as a pointer
name = malloc(256); // allocate a new memory block and assign a pointer to it to name
scanf("%s" , name); // No & needed because name is already a pointer
rec.name = name; // No & needed because name is already a pointer

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM