尝试打开非常大的文件时,使用open命令出错

时间:2010-01-15 03:29:09

标签: c linux unix networking gdb

我正在学校上网,并且是第一次使用C / GDB。我们的任务是创建一个与客户端浏览器通信的Web服务器。我正在进行中,可以打开文件并将其发送给客户端。一切都很顺利,直到我打开一个非常大的文件,然后我就错了。我不是C / GDB的专业人员,所以我很抱歉,如果这导致我问愚蠢的问题而不能自己看到解决方案,但当我看到倾销的核心时,我看到我的seg故障来到这里:< / p>

if (-1 == (openfd = open(path, O_RDONLY)))

具体来说,我们的任务是打开文件并将其发送到客户端浏览器。我的算法是:

  1. 打开/错误捕获
  2. 将文件读入缓冲区/错误捕获
  3. 发送文件
  4. 我们的任务还包括确保在发送非常大的文件时服务器不会崩溃。但我的问题似乎是打开它们。我可以发送所有较小的文件。有问题的文件是29.5MB。

    整个算法是:

    ssize_t send_file(int conn, char *path, int len, int blksize, char *mime) {
      int openfd; // File descriptor for file we open at path
      int temp; // Counter for the size of the file that we send
      char buffer[len]; // Buffer to read the file we are opening that is len big
    
      // Open the file
      if (-1 == (openfd = open(path, O_RDONLY))) {
        send_head(conn, "", 400, strlen(ERROR_400));
        (void) send(conn, ERROR_400, strlen(ERROR_400), 0);
        logwrite(stdout, CANT_OPEN);
        return -1;
      }
    
      // Read from file
      if (-1 == read(openfd, buffer, len)) {
        send_head(conn, "", 400, strlen(ERROR_400));
        (void) send(conn, ERROR_400, strlen(ERROR_400), 0);
        logwrite(stdout, CANT_OPEN);
        return -1;
      }
      (void) close(openfd);
    
      // Send the buffer now
      logwrite(stdout, SUC_REQ);
      send_head(conn, mime, 200, len);      
      send(conn, &buffer[0], len, 0);
      return len;
    }
    

    我不知道如果这只是一个事实,我是Unix / C新手。对不起,如果是的话。 =(但你非常感谢你的帮助。

4 个答案:

答案 0 :(得分:4)

我可能只是误解你在你的问题中的意思,但我觉得我应该指出,一般来说,尝试一次阅读整个文件是个坏主意,以防你处理的事情只是对你的记忆来说太大了。

分配一个特定大小的缓冲区更聪明,比如说8192字节(好吧,这就是我倾向于做很多事情,无论如何),并且只需要一直阅读和发送那么多,直到你的阅读( )操作为流结束返回0(并且没有设置errno)。

答案 1 :(得分:4)

我怀疑你有一个stackoverflow(我应该在这个网站上使用该术语获得奖励积分)。

问题是你是在同一时间为堆栈上的整个文件分配缓冲区。对于较大的文件,此缓冲区大于堆栈,并且下次尝试调用函数(并因此在堆栈上放置一些参数)时程序崩溃。

崩溃出现在打开的行上,因为在堆栈上分配缓冲区实际上并没有写入任何内存,它只是更改堆栈指针。当您打开调用尝试将参数拖入堆栈时,堆栈顶部现在已经溢出,这会导致崩溃。

解决方案如Platinum Azure或dreamlax建议的那样,一次读取文件中的小位或在堆上分配缓冲区将malloc或new。

答案 2 :(得分:3)

可能尝试使用malloc分配内存,而不是使用可变长度数组。

char *buffer = malloc (len);

...

free (buffer);

我刚刚在我的系统上进行了一些简单的测试,当我使用大尺寸的可变长度数组(就像你遇到麻烦的那样)时,我也得到了一个SEGFAULT。

答案 3 :(得分:2)

你正在堆栈上分配缓冲区,而且它太大了。

当您在堆栈上分配存储时,所有编译器都会减少堆栈指针,以便腾出足够的空间(这会将堆栈变量分配保持为恒定时间)。它不会尝试触摸任何这种堆叠的内存。然后,当你调用open()时,它会尝试将参数放在堆栈上,并发现它已经溢出堆栈并死掉。

您需要以块的形式对文件进行操作,对其进行内存映射(mmap())或malloc()存储。 此外,path应声明为const char*