【发布时间】:2010-10-26 12:31:07
【问题描述】:
请帮助我理解为什么这个函数在到达 fclose 时会抛出异常:
void receive_file(int socket, char *save_to, int file_size) {
FILE *handle = fopen(save_to,"wb");
if(handle != NULL) {
int SIZE = 1024;
char buffer[SIZE];
memset(buffer,0,SIZE);
int read_so_far = 0;
int read_now = 0;
int reading_unit = (file_size < SIZE) ? file_size : SIZE;
do {
read_now = read(socket,buffer,reading_unit);
fwrite(buffer,read_now,1,handle);
read_so_far += read_now;
if(read_so_far >= file_size) {
break;
}
memset(buffer, 0, sizeof(buffer));
} while (1);
read_now = 0;
fclose(handle);
}
else {
extern int errno;
printf("error creating file");
printf(" error code : %d",errno);
exit(-1);
}
}
Eclipse CDT 存在,但出现以下错误:
单步执行直到退出函数__kernel_vsyscall, 没有行号信息。
这个函数的目的是通过socket接收一个文件。
编辑:我使用的是 CentOS 5.3。问题是,文件被创建和写入。甚至 MD5 也是正确的。我不明白为什么它在 fclose 失败。
EDIT2:这是我设法获得的堆栈跟踪:
*** 检测到 glibc *** /home/linuser/workspace/proj/Debug/proj: free(): 下一个大小无效(正常):0x096a0068 *** ======= 回溯:========= /lib/libc.so.6[0x4fb0f1] /lib/libc.so.6(cfree+0x90)[0x4febc0] /lib/libc.so.6(fclose+0x136)[0x4e9c56] /home/linuser/workspace/proj/Debug/proj[0x8048cd8] /home/linuser/workspace/proj/Debug/proj[0x80492d6] /home/linuser/workspace/proj/Debug/proj[0x804963d] /lib/libc.so.6(__libc_start_main+0xdc)[0x4a7e8c] /home/linuser/workspace/proj/Debug/proj[0x8048901] ======= 内存映射:======== 001ff000-00200000 r-xp 001ff000 00:00 0 [vdso] 0046f000-00489000 r-xp 00000000 08:06 1280361 /lib/ld-2.5.so 00489000-0048a000 r-xp 00019000 08:06 1280361 /lib/ld-2.5.so 0048a000-0048b000 rwxp 0001a000 08:06 1280361 /lib/ld-2.5.so 00492000-005d0000 r-xp 00000000 08:06 1280362 /lib/libc-2.5.so 005d0000-005d2000 r-xp 0013e000 08:06 1280362 /lib/libc-2.5.so 005d2000-005d3000 rwxp 00140000 08:06 1280362 /lib/libc-2.5.so 005d3000-005d6000 rwxp 005d3000 00:00 0 005d8000-005fd000 r-xp 00000000 08:06 1280369 /lib/libm-2.5.so 005fd000-005fe000 r-xp 00024000 08:06 1280369 /lib/libm-2.5.so 005fe000-005ff000 rwxp 00025000 08:06 1280369 /lib/libm-2.5.so 009b2000-009bd000 r-xp 00000000 08:06 1280372 /lib/libgcc_s-4.1.2-20080825.so.1 009bd000-009be000 rwxp 0000a000 08:06 1280372 /lib/libgcc_s-4.1.2-20080825.so.1 009c5000-00aa5000 r-xp 00000000 08:06 5465873 /usr/lib/libstdc++.so.6.0.8 00aa5000-00aa9000 r-xp 000df000 08:06 5465873 /usr/lib/libstdc++.so.6.0.8 00aa9000-00aaa000 rwxp 000e3000 08:06 5465873 /usr/lib/libstdc++.so.6.0.8 00aaa000-00ab0000 rwxp 00aaa000 00:00 0 08048000-0804a000 r-xp 00000000 08:06 4884214 /home/linuser/workspace/proj/Debug/proj 0804a000-0804b000 rw-p 00001000 08:06 4884214 /home/linuser/workspace/proj/Debug/proj 096a0000-096c1000 rw-p 096a0000 00:00 0 [堆] b7e00000-b7e21000 rw-p b7e00000 00:00 0 b7e21000-b7f00000 ---p b7e21000 00:00 0 b7f99000-b7f9a000 rw-p b7f99000 00:00 0 b7faa000-b7fac000 rw-p b7faa000 00:00 0 bfa82000-bfa97000 rw-p bffea000 00:00 0 [堆栈]这里是函数的“更新”版本:
void rec_file(int socket,char *path,int size)
{
FILE *handle = fopen(path,"wb");
char buffer[4096];
int total_read = 0;
if(handle != NULL)
{
while(1)
{
int bytes_read = recv(socket,buffer,4096,0);
total_read += bytes_read;
if(bytes_read != -1)
{
fwrite(buffer,bytes_read,1,handle);
}
else
{
printf("read error ");
exit(-1);
}
if(total_read >= size)
{
break;
}
}
fclose(handle);
}
else
{
printf("error receiving file");
exit(-1);
}
}
也许这更干净?但是,我仍然收到相同的 fclose 异常。
编辑3: 我注释掉了所有内容,只留下了以下代码,遗憾的是,它仍然在 fclose 处引发异常:
void nrec(int sock,char* path,int size)
{
FILE *handle = fopen(path,"wb");
if(handle == NULL)
{
printf ("error opening file");
return;
}
fclose(handle);
}
【问题讨论】:
-
不要写'extern int errno;' -- 使用#include
;因为 'errno' 是一个可修改的整数 l 值,但不一定是 int。在多线程编程中,通常是#define errno *(errno_func()) where extern int *errno_func(void); -
你排除了save_to(你要写入的文件名)不是垃圾吗?还有,什么操作系统?
-
memset() 操作并不是真正需要的。
-
另外,在上下文中使用 VLA 是不寻常且不必要的。您应该知道它是一个 C99 构造。
-
还有一个:仅当 bytes_read 大于零时才进行写入。