我正在学校上网,并且是第一次使用C / GDB。我们的任务是创建一个与客户端浏览器通信的Web服务器。我正在进行中,可以打开文件并将其发送给客户端。一切都很顺利,直到我打开一个非常大的文件,然后我就错了。我不是C / GDB的专业人员,所以我很抱歉,如果这导致我问愚蠢的问题而不能自己看到解决方案,但当我看到倾销的核心时,我看到我的seg故障来到这里:< / p>
if (-1 == (openfd = open(path, O_RDONLY)))
具体来说,我们的任务是打开文件并将其发送到客户端浏览器。我的算法是:
我们的任务还包括确保在发送非常大的文件时服务器不会崩溃。但我的问题似乎是打开它们。我可以发送所有较小的文件。有问题的文件是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新手。对不起,如果是的话。 =(但你非常感谢你的帮助。
答案 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*
。