使用read从二进制文件读取struct

时间:2014-02-02 20:39:08

标签: c file struct

我在C中对复杂的客户端/服务器(多聊天室)程序进行简单的操作。

我有一个名为 node 的链接列表结构

struct node
{
    char *user;
    char *passwd;
    int id;
    int connected;
    struct node *next;
};

另一种名为 room

的结构
struct room
{
    char *name;
    int capacity;
    int room_id;
    int admin_id;
    struct room *next;
    struct node *users;
};

我将此声明为全局变量:

struct room *rooms = NULL;

我已经使用互斥锁和信号量保护它。

所以我只想在服务器结束时编写这个结构,然后在服务器再次启动时加载它。这样做的逻辑在于两个文件, server.c * server_utils.c * ,如下所示:

server.c

int main (void)
{
    [...]
    struct stat st;
    [...]
    stat ("rooms.bin", &st);
    if (st.st_size > 0)
    {
        // Load rooms
        load_rooms ();
    }
    else
    {
        [...]
    }
    [...]
    exit (EXIT_SUCCESS);
}

*的 server_utils.c *

[...]

void load_rooms (void)
{
    int fd;
    if ((fd = open ("rooms.bin", O_RDONLY)) < 0)
    {
        perror ("open");
        exit (EXIT_FAILURE);
    }
    else
    {
        read (fd, &rooms, sizeof (rooms));
    }
}

void save_rooms (void)
{
    int fd;
    if ((fd = open ("rooms.bin", O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0)
    {
        perror ("open");
        exit (EXIT_FAILURE);
    }
    else
    {
        write (fd, &rooms, sizeof (rooms));
    }
}

[...]

我发现的问题是当我用

从二进制文件中读取结构时
read (fd, &rooms, sizeof (rooms));

然后我尝试用

打印结构
void rooms_linkedlist_print (struct room *head)
{
    struct room *curr = head;
    char str[1024];
    while (curr != NULL)
    {
        write (1, curr->name, strlen (curr->name));
        write (1, "\n", strlen ("\n"));
        bzero (str, 1024);
        sprintf (str, "%d\n", curr->capacity);
        write (1, str, strlen (str));
        bzero (str, 1024);
        sprintf (str, "%d\n", curr->room_id);
        write (1, str, strlen (str));
        bzero (str, 1024);
        sprintf (str, "%d\n", curr->admin_id);
        write (1, str, strlen (str));
        curr = curr->next;
    }
}

我遇到了分段错误(核心转储)。关于我做错了什么想法?

1 个答案:

答案 0 :(得分:2)

你的房间结构里面有指针。

当您重新加载数据时,这些指针将不再一定指向已分配的内存,从而导致分段错误。

您可以通过将指针更改为使用索引更改为rooms数组来解决此问题。