【问题标题】:Why do I get segmentation fault using fopen?为什么我使用 fopen 会出现分段错误?
【发布时间】:2021-06-30 08:35:22
【问题描述】:

我正在用 C 语言编写一个使用 fifos 的客户端-服务器模型。我发送一个文件名和一个唯一 fifo 的名称,供客户端从客户端接收数据,然后服务器打开文件并将其第一行写入 fifo。问题是即使文件存在,我在打开它时也会遇到分段错误。似乎fopen() 函数有效,但我仍然收到错误消息。如果文件不存在,它只会发送一个空字符串。

这里是client.c

#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

#define BUFSIZE 512

struct sent {
   char name[BUFSIZE];
   char fifo[BUFSIZE];
};


int main()
{
   char name[BUFSIZE];
   char recieved[BUFSIZE];

   int client_server_fifo;
   char cs_fifo[BUFSIZE] = "cs_fifo";

   int server_client_fifo;
   char sc_fifo[BUFSIZE];
   sprintf(sc_fifo, "sc_fifo_%d", getpid());

   struct sent *sent;

   mkfifo(sc_fifo, 0777); 

   while(1) {
      printf("Write the name of the file: ");
      scanf("%s", name);

      printf("1111\n");
      client_server_fifo = open(cs_fifo, O_WRONLY);
      printf("2222\n");
      
      printf("%s", name);
      printf("%s", cs_fifo);

      sent->name = name;
      sent->fifo = cs_fifo;

      printf("%s", name);
      printf("%s", cs_fifo);

      write(client_server_fifo, sent, sizeof(*sent));

      server_client_fifo = open(sc_fifo, O_RDONLY);

      if (read(server_client_fifo, recieved, sizeof(recieved)) == -1) {
         printf("An error ocurred.\n");
      } else {
         printf("First line of the file: \n%s\n", recieved);
         close(client_server_fifo);
         close(server_client_fifo);
      }
      memset(recieved, 0, sizeof(recieved));
   }

   return 0;
}

这里是server.c

#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

#define BUFSIZE 512

struct sent {
   char name[BUFSIZE];
   char fifo[BUFSIZE];
};


int main()
{
   int client_server_fifo;
   char cs_fifo[BUFSIZE] = "cs_fifo";

   int server_client_fifo;
   char sc_fifo[BUFSIZE];

   struct sent *sent;

   char name[BUFSIZE]; 
   char line[BUFSIZE]; 

   FILE *file; 

   printf("Server running...\n");
     
   mkfifo(cs_fifo, 0777); 
   
   while (1)
   {
      client_server_fifo = open(cs_fifo, O_RDONLY); 

      read(client_server_fifo, sent, sizeof(*sent)); 

      strcpy(name, sent->name);
      strcpy(sc_fifo, sent->fifo);

      if((file = fopen(name, "r")) != NULL) { 
         printf("%s\n", name);
         fgets(line, BUFSIZE, file); 
         printf("%s\n", name);
      }
    
      server_client_fifo = open(sc_fifo, O_WRONLY);

      write(server_client_fifo, line, strlen(line)); 
      
      memset(name, 0, sizeof(name));
      memset(line, 0, sizeof(line));

      close(client_server_fifo);

   }
   return 0;
}

为什么会这样?

【问题讨论】:

  • 请为崩溃的程序创建一个minimal reproducible example。然后在调试器中运行它以准确定位崩溃发生的时间和地点,并检查相关变量的值。
  • 我正在使用 ssh 在远程服务器中执行此操作。在这里,我有 3 个名为 fitx1、fitx2 和 fitx3 的文件。从客户端发送文件名时,服务器工作正常,直到 fopen 所在的位置,它不会打印其中的内容,然后执行因分段错误而停止。
  • 虽然有几点:你为什么使用malloc 来表示单个sent 结构?如果您无法打开文件会发生什么(特别是在这种情况下,line 的内容是什么)?所有字符串都以空值结尾吗?如果其他地方出现错误会发生什么(总是进行错误检查!)?
  • 如果您还没有这样做,那么花点时间阅读the help pages,阅读SO tour,阅读How to Ask,以及作为this question checklist
  • 谁教你像这样把代码塞进一行:if (read(server_client_fifo, recieved, sizeof(recieved)) == -1)?祝你好运,尝试完全处理 read() 可以返回的所有事情,当您将调用塞进这样的 if 语句中时。 read() 可以返回 any 值,最多包括您请求读取的字节数。它可以在失败时返回-1。它可以在 EOF 上返回 0。它可以返回部分结果,这意味着您必须再次调用read()。当调用被塞进if() 语句时,您无法处理所有这些。此外,read() 不会产生字符串。

标签: c client-server fopen fifo


【解决方案1】:

程序有未定义的行为,因为在 gthis 语句中

sprintf(sc_fifo, "sc_fifo_%d", getpid());

您正在尝试更改指针 sc_fifo 指向的字符串文字。

char *cs_fifo = "cs_fifo";

当您声明指向字符串文字的指针时,请始终使用限定符 const 声明它们。在这种情况下,如果您将托盘更改字符串文字,您将在编译时收到禁止错误。

你也使用了未初始化的指针发送

struct sent *sent;

在此声明中

read(client_server_fifo, sent, sizeof(*sent)); 

还有其他错误。例如数组没有赋值运算符。所以client.c中的这些语句

  sent->name = name;
  sent->fifo = cs_fifo;

不正确。

【讨论】:

    猜你喜欢
    • 2018-01-07
    • 2011-04-23
    相关资源
    最近更新 更多