2014-01-28 5 views
2

내 코드가 segfaulting이고 무엇이 잘못되었는지 전혀 모른다. 가능한 한 간소화했지만 문제는 찾을 수 없습니다.C - fclose() 호출로 코어 덤프

C 파일 TEST.C :

$ gcc --version 
gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 
Copyright (C) 2013 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
$ gcc -Wall -g test.c && gdb a.out 
GNU gdb (GDB) 7.6.1-ubuntu 
Copyright (C) 2013 Free Software Foundation, Inc. 
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 
This is free software: you are free to change and redistribute it. 
There is NO WARRANTY, to the extent permitted by law. Type "show copying" 
and "show warranty" for details. 
This GDB was configured as "x86_64-linux-gnu". 
For bug reporting instructions, please see: 
<http://www.gnu.org/software/gdb/bugs/>... 
Reading symbols from /home/dberg/ITX/Cells/test/a.out...done. 
(gdb) break 26 
Breakpoint 1 at 0x400739: file test.c, line 26. 
(gdb) run test.txt 
Starting program: /home/dberg/ITX/Cells/test/a.out test.txt 

Breakpoint 1, main (argc=2, argv=0x7fffffffdf48) at test.c:26 
26   fclose(fh); 
(gdb) n 

Program received signal SIGSEGV, Segmentation fault. 
__GI___libc_free (mem=0x1) at malloc.c:2892 
2892 malloc.c: No such file or directory. 
(gdb) 

되지 않는 구조체 멤버 중 하나를 삭제 : 실행하고 gdb를 통해 실행

#include <stdlib.h> 
#include <stdio.h> 

struct container { 
    void *A[3], *B[3], *C[3], *D[3]; 
    int x, y, z; 
}; 

int main (int argc, char* argv[]) { 
    struct container *cont = malloc (sizeof cont); 
    FILE* fh = fopen(argv[1], "r"); 
    if(fh == NULL) return 0; 
    fscanf(fh, "%d %d", &cont->y, &cont->z); 
    fclose(fh); 
    free(cont); 

    return 0; 
} 

있는 test.txt의 내용

1 1 

코드를 오류없이 실행할 수 있습니다. 사용되지 않는 구조체 멤버 중 하나를 구조체의 끝으로 이동하거나 1 또는 모든 배열의 크기를 줄이면 코드가 성공적으로 실행될 수 있습니다. segfault에 fscanf() 호출이 필요합니다.

구문이 잘못되었으며 구조체의 크기가이 버그에 너무 중요한 이유는 무엇입니까?

+3

힌트 : 'sizeof cont'란 무엇입니까? – Mysticial

+0

표제 : 멋지게 형성된 질문입니다. – chux

답변

4

struct container *cont = malloc (sizeof cont);*가 누락되었으므로 sizeof *cont이 필요합니다.

+0

당신이 그것을 할 수 있다는 것을 알지 못했습니다. (cont를 선언 한 문장의 sizeof에있는 cont를 참조하십시오) – pm100

+1

'malloc (sizeof struct container)'는보다 직관적 인 방법 일 수 있습니다 – harmic

+0

'struct container * cont = malloc sizeof * cont);'더 직관적이고 유지하기 쉽습니다. – chux

0

Bzzzt! 실패하고있는 fclose가 아니라, malloc'ing (struct container) 타입을 담을 공간이 충분하지 않다는 것입니다. 구문 학적 문제가 아닌 의미론입니다.

을 포함, 당신은 "물건"라는 파일을 가지고 있다고 가정 :

1,2,3 

그리고 프로그램이 doit.c라는, 그리고는 fopen과에서 반환 값을 확인, 충분한 인수 확인이 파일을 (읽고 의 malloc 등),

//you might want to carry a shorter name around, 
typedef struct container_s 
{ 
    void *A[3], *B[3], *C[3], *D[3]; 
    int x, y, z; 
} container; 
//how big is a (struct container)? depends. How big is a (void*) or an (int)? 
//Suppose 32-bit, then you have 12x4+3*4=60 bytes. 
//Suppose 64-bit pointer, and 32-bit integer, then you have 12x8+3*4=108 bytes. 

int main (int argc, char* argv[]) 
{ 
    struct container* cont; 
    FILE* fh = fopen(argv[1], "r"); 
    char* filename=NULL; 
    //you really should not examine argv[1] if there is no argument... 
    if(argc<1) { 
     printf("usage: stuff <filename>\n"); 
     exit(EXIT_FAILURE); 
    } 
    filename=argv[1]; 
    //allocate space for a (struct container_s) 
    if(!(cont = malloc(sizeof(struct container)))) { 
     printf("error: cannot allocate container\n"); 
    } 
    //check that file opens successfully, 
    if(!(fh=fopen(filename,"r"))) { 
     printf("error: cannot open %s\n",filename); 
     return 0; 
    } 
    //read your vector (x,y,z), 
    fscanf(fh,"%d,%d,%d",&(cont->x),&(cont->y),&(cont->z)); 
    //for fun, print the (x,y,z) coordinates, 
    printf("stuff(%d,%d,%d)\n",cont->x,cont->y,cont->z); 
    fclose(fh); 
    free(cont); 

    return 0; 
} 

컴파일하고 위의를 실행하고 당신이 얻을,

./doit stuff 
stuff(1,2,3) 

하세요 라이브러리 함수 (fopen, malloc)와 바운드 검사 배열 (argv [] 등)의 반환 값을 확인하십시오. 아, 컨테이너에 A [], B [], C [] 및 D []에 대한 상징적 인 이름을 지정하고 싶을 수도 있습니다.