c - 为什么这个 C 函数在 fclose 时崩溃?

标签 c exception function

请帮助我理解为什么这个函数在到达 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 存在以下错误:

Single stepping until exit from function __kernel_vsyscall, 
which has no line number information.

The purpose of this function is to receive a file through a socket.

EDIT: I'm using CentOS 5.3. The thing is, the file is created and written. Even the MD5 is correct. I don't understand why it's failing at fclose.

EDIT2: here is a stack trace I managed to get :

*** glibc detected *** /home/linuser/workspace/proj/Debug/proj: free(): invalid next size (normal): 0x096a0068 ***
======= Backtrace: =========
/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]
======= Memory map: ========
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          [heap]
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          [stack]

and here is the "updated" version of the function :


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);
}

最佳答案

  • fclose() 返回一个值:如果文件关闭成功则为 0,否则为 EOF。考虑将您的代码修改为...

    if (fclose(handle)) { printf("错误关闭文件。");退出(-1);

  • 正如其他人指出的那样,检查 read() 是否有错误。

  • 如果崩溃发生在之后 fclose 返回 0(成功),并且所有 read() 都成功,那么问题可能出在别处。也许是 VLA。考虑将缓冲区代码更改为静态文件或 malloc/free。

  • 如果调用者弄错了文件大小,例如声称文件为 500 字节,而实际上只有 480 字节,您的代码会一直读取套接字吗?

关于c - 为什么这个 C 函数在 fclose 时崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/868992/

相关文章:

c - 为什么 sizeof ('a' ) 在 C 中是 4?

haskell - 如何将此函数从 ExceptT 转换为 Haskell 中的 Except?

java - Sonarqube和处理异常机制

mysql - mysql中的函数可以返回结果集吗?如果没有,可能的替代解决方案是什么?

r - 在 R 中绘制 Haar 函数

c - C 中的 DNS 客户端

c - do-while 循环中的 scanf() 会导致无限循环,即使测试输入也是如此

c - 地址转换示例

Scala: Value::不是 Int 的成员

javascript - Chrome 扩展函数返回未定义的字符串