Question

My code is segfaulting and I have no idea what is wrong. I've simplified it as far as I can but still can't find a problem.

C File 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;
}

Contents of test.txt

1 1

Executing and running through 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) 

Deleting any one of the unused struct members allows the code to execute without error. Moving any of the unused struct members to the end of the struct or decreasing the size of any 1 or all arrays also allows the code to execute successfully. The presence of the fscanf() call is also necessary for the segfault

Where is my syntax wrong and why is the size of the struct so critical to this bug?

Was it helpful?

Solution

There's a * missing in struct container *cont = malloc (sizeof cont);, you need sizeof *cont.

OTHER TIPS

Bzzzt! It is not fclose that is failing, it is that you are not malloc'ing enough space to hold a (struct container) type. Which is a semantic rather than syntactic problem.

Suppose you have a file, called "stuff", containing:

1,2,3

And your program is named doit.c, and it reads this file (checking for enough arguments, checking return values from fopen and malloc, etc),

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

Compile and run the above, and you get,

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

Please check the return values from library functions (fopen, malloc) and bounds check arrays (such as argv[]). Oh, and you might want to give a symbolic name for A[], B[], C[], and D[] in your container.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top