2

我的代码有段错误,我不知道出了什么问题。我已经尽可能地简化了它,但仍然找不到问题。

C 文件 test.c:

#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

通过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() 调用的存在

我的语法哪里错了,为什么结构的大小对这个错误如此重要?

4

2 回答 2

4

*缺少struct container *cont = malloc (sizeof cont);,您需要sizeof *cont

于 2014-01-28T23:29:25.603 回答
0

啧啧!失败的不是 fclose,而是您没有分配足够的空间来容纳(结构容器)类型。这是一个语义而不是句法问题。

假设您有一个名为“stuff”的文件,其中包含:

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[] 指定一个符号名称。

于 2014-01-29T00:08:37.817 回答