C - Сброс ядер с вызовом fclose()

Мой код segfaulting, и я понятия не имею, что не так. Я упростил это, насколько я могу, но все еще не могу найти проблему.

Файл 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() также необходимо для segfault

Где мой синтаксис неправильный и почему размер структуры так важен для этой ошибки?

2 ответа

Решение

Есть * отсутствует в struct container *cont = malloc (sizeof cont);, тебе нужно sizeof *cont,

Bzzzt! Это не сбой fclose, это то, что вы не используете malloc достаточно места для хранения типа (struct container). Что является скорее семантической, чем синтаксической проблемой.

Предположим, у вас есть файл с именем "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[] в вашем контейнере.

Другие вопросы по тегам