2014-01-28 58 views
2

我的代碼是segfaulting,我不知道什麼是錯的。我儘可能簡化了它,但仍然無法找到問題。C - 調用fclose轉儲內核()

C語言文件test.c的:test.txt的

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

內容

1 1 

執行和通過GDB運行:

$ 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) 

刪除未使用的結構成員中的任何一個允許代碼無誤地執行。將任何未使用的結構成員移動到結構的結尾或減小任何1或全部數組的大小也允許代碼成功執行。 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!這不是失敗,這是因爲你沒有足夠的空間來容納(結構容器)類型。這是一個語義問題而不是句法問題。

假設你有一個文件,叫「東西」,包括:

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 []提供一個符號名稱。