Pourquoi est-ce une fonction C se planter à fclose?

S'il vous plaît aidez-moi à comprendre pourquoi cette fonction déclenche une exception lorsqu'il atteint 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 existe avec l'erreur suivante :

Le pas à pas jusqu'à la sortie de la fonction __kernel_vsyscall, 
qui n'a pas de numéro de ligne de l'information.

Le but de cette fonction est de recevoir un fichier via une socket.

EDIT: je suis sous CentOS 5.3. Le truc, c'est que le fichier est créé et écrit. Même le MD5 est correct. Je ne comprends pas pourquoi il est en situation d'échec fclose.

EDIT2: voici une trace de la pile, j'ai réussi à obtenir :

*** glibc détecté *** /home/linuser/espace de travail/proj/Debug/proj: free(): invalid suivant la taille (normal): 0x096a0068 *** 
======= Backtrace: ========= 
/lib/libc.donc.6[0x4fb0f1] 
/lib/libc.donc.6(bgratuit+0x90)[0x4febc0] 
/lib/libc.donc.6(fclose+0x136)[0x4e9c56] 
/home/linuser/espace de travail/proj/Debug/proj[0x8048cd8] 
/home/linuser/espace de travail/proj/Debug/proj[0x80492d6] 
/home/linuser/espace de travail/proj/Debug/proj[0x804963d] 
/lib/libc.donc.6(__libc_start_principaux+0xdc)[0x4a7e8c] 
/home/linuser/espace de travail/proj/Debug/proj[0x8048901] 
======= Carte mémoire: ======== 
001ff000-00200000 r-xp 001ff000 00:00 0 [vdso] 
0046f000-00489000 r-xp 00000000 08:06 1280361 /lib/ld-2.5.donc 
00489000-0048a000 r-xp 00019000 08:06 1280361 /lib/ld-2.5.donc 
0048a000-0048b000 rwxp 0001a000 08:06 1280361 /lib/ld-2.5.donc 
00492000-005d0000 r-xp 00000000 08:06 1280362 /lib/libc-2.5.donc 
005d0000-005d2000 r-xp 0013e000 08:06 1280362 /lib/libc-2.5.donc 
005d2000-005d3000 rwxp 00140000 08:06 1280362 /lib/libc-2.5.donc 
005d3000-005d6000 rwxp 005d3000 00:00 0 
005d8000-005fd000 r-xp 00000000 08:06 1280369 /lib/libm-2.5.donc 
005fd000-005fe000 r-xp 00024000 08:06 1280369 /lib/libm-2.5.donc 
005fe000-005ff000 rwxp 00025000 08:06 1280369 /lib/libm-2.5.donc 
009b2000-009bd000 r-xp 00000000 08:06 1280372 /lib/libgcc_s-4.1.2-20080825.donc.1 
009bd000-009be000 rwxp 0000a000 08:06 1280372 /lib/libgcc_s-4.1.2-20080825.donc.1 
009c5000-00aa5000 r-xp 00000000 08:06 5465873 /usr/lib/libstdc++.donc.6.0.8 
00aa5000-00aa9000 r-xp 000df000 08:06 5465873 /usr/lib/libstdc++.donc.6.0.8 
00aa9000-00aaa000 rwxp 000e3000 08:06 5465873 /usr/lib/libstdc++.donc.6.0.8 
00aaa000-00ab0000 rwxp 00aaa000 00:00 0 
08048000-0804a000 r-xp 00000000 08:06 4884214 /home/linuser/espace de travail/proj/Debug/proj 
0804a000-0804b000 rw-p 00001000 08:06 4884214 /home/linuser/espace de travail/proj/Debug/proj 
096a0000-096c1000 rw-p 096a0000 00:00 0 [tas] 
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 [pile] 

et voici la "mise à jour" de la version de la fonction :


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

c'est peut-être plus propre? Cependant, je continue à recevoir les mêmes fclose exception.

EDIT3:
J'ai commenté tout et je n'ai plus quitté le code suivant, qui, malheureusement, jette toujours l'exception à la fonction fclose :


void nrec(int sock,char* path,int size)
{
    FILE *handle = fopen(path,"wb");
    if(handle == NULL)
    {
        printf ("error opening file");
        return;
    }
    fclose(handle);
}
  • Ne pas écrire " extern int errno;' -- utiliser #include <errno.h>; parce que "errno" est modifiable entier l-valeur, mais pas nécessairement un int. En multi-thread de programmation, il est habituellement #define errno *(errno_func()) où extern int *errno_func(void);
  • Avez-vous exclu que save_to (le nom du fichier que vous souhaitez écrire) n'est pas la poubelle? Aussi, ce système d'exploitation?
  • Le memset() les opérations ne sont pas vraiment nécessaires.
  • Aussi, à l'aide d'un VLA est ... inhabituel et inutiles dans le contexte. Vous devez être conscient que c'est un C99 construire.
  • Un de plus: l'écriture si bytes_read est supérieure à zéro.
  • Vous gardez en disant: "lève une exception" - que voulez-vous dire de la baie qui? Êtes-vous à l'aide de C ou C++? Dans les deux cas une exception ne doit jamais être jeté par un appel à la fonction fclose().
  • Je me suis habitué à la programmation orientée objet de la terminologie. Pensez à cela comme une erreur d'exécution, si cela aide.

InformationsquelleAutor Geo | 2009-05-15