Ошибка сегментации - может ли другая версия glib-c делать что-то подобное? - PullRequest
0 голосов
/ 26 февраля 2012

У меня проблемы с выделением / освобождением памяти.

На «64-битной машине» я запускаю некоторый c-код, который не дал мне никакой ошибки. Если я запускаю тот же код на 32-битной машине (после его повторной компиляции, obv.), У меня возникает проблема с ошибкой сегментации.

Это моя версия glib-c:

Пакет: libc6
Новый: да Состояние: установлено Автоматически устанавливается: нет Версия: 2.13-20ubuntu5 Приоритет: требуется Раздел: libs Сопровождающий: разработчики Ubuntu Несжатый размер: 10,7 M Зависит от: libc-bin (= 2.13-20ubuntu5), libgcc1, tzdata Предлагает: glibc-doc, debconf | debconf-2.0, локали Конфликты: belocs-locales-bin, belocs-locales-bin, libc6-amd64, libc6-amd64, prelink (<0.0.20090925), prelink (<0.0.20090925), tzdata (< 2007k-1), tzdata (<2007k-1), tzdata-etch, tzdata-etch Перерывы: nscd (<2.13), nscd (<2.13), libc6 (! = 2.13-20ubuntu5) Заменяет: belocs-locales-bin, belocs-locales-bin, libc6-amd64, libc6-amd64, libc6 (<2.13-20ubuntu5) Обеспечивает: glibc-2.13-1 Описание: библиотека libreria C GNU: библиотека librerie </p>

На 32-битной машине версия:

2.06-01

Более того, вот фрагмент кода, который сводит меня с ума:

void estrai_libro (FILE* fileDescriptor, Libro* libroLetto) {

char* ptr_buf;
size_t n;
size_t lung;
ssize_t nread;

/* ---- questo blocco di istruzioni verrà utilizzato per tutti
    i campi della struttura Libro passata in input */
/* inizializzo ptr_buf e n rispettivamente a NULL e a 0 in moda da
   da sfruttare al meglio la getline(...)*/     
ptr_buf = NULL;
n = 0;
/* copio all'interno del buffer ptr_buf il contenuto di una riga
       del file; la funzione getline legge dal file fino a quando non
   incontra uno \n (ecco perchè io formatto gli input) */
nread = getline (&ptr_buf, &n, fileDescriptor);
/* calcolo la lunghezza della stringa letta */
lung = strlen (ptr_buf);
/* istanzio una zona di memoria della stessa dimensione della stringa
   letta e fatta puntare dal campo titolo della struttura Libro */
libroLetto->titolo = (char*) malloc (lung*sizeof(char));
/* inizializzo la zona di memoria istanziata con degli 0 */
memset (libroLetto->titolo, 0, sizeof(libroLetto->titolo));
/* copio la stringa letta e contenuta in ptr_buf nel campo titolo
   della struttura Libro passata in input (libroLetto). */
strcpy (libroLetto->titolo,ptr_buf);
free (ptr_buf);
/* ---- fine blocco*/
ptr_buf = NULL;
n = 0;
nread = getline (&ptr_buf, &n, fileDescriptor);
lung = strlen (ptr_buf);
libroLetto->autore = (char*) malloc (lung*sizeof(char));
memset (libroLetto->autore, 0, sizeof(libroLetto->autore));
strcpy (libroLetto->autore,ptr_buf);
free (ptr_buf);
ptr_buf = NULL;
n = 0;
nread = getline (&ptr_buf, &n, fileDescriptor);
lung = strlen (ptr_buf);
libroLetto->editore = (char*) malloc (lung*sizeof(char));
memset (libroLetto->editore, 0, sizeof(libroLetto->editore));
strcpy (libroLetto->editore,ptr_buf);
free (ptr_buf);
ptr_buf = NULL;
n = 0;
nread = getline (&ptr_buf, &n, fileDescriptor);
lung = strlen (ptr_buf);
libroLetto->data_pubblicazione = (char*) malloc (lung*sizeof(char));
memset (libroLetto->data_pubblicazione, 0, sizeof(libroLetto->data_pubblicazione));
strcpy (libroLetto->data_pubblicazione,ptr_buf);
free (ptr_buf);
ptr_buf = NULL;
n = 0;
nread = getline (&ptr_buf, &n, fileDescriptor);
lung = strlen (ptr_buf);
libroLetto->num_pagine = (char*) malloc (lung*sizeof(char));
memset (libroLetto->num_pagine, 0, sizeof(libroLetto->num_pagine));
strcpy (libroLetto->num_pagine,ptr_buf);
free (ptr_buf); 
ptr_buf = NULL;
n = 0;
nread = getline (&ptr_buf, &n, fileDescriptor);
lung = strlen (ptr_buf);
libroLetto->num_copie = (char*) malloc (lung*sizeof(char));
memset (libroLetto->num_copie, 0, sizeof(libroLetto->num_copie));
strcpy (libroLetto->num_copie,ptr_buf);
free (ptr_buf);
ptr_buf = NULL;
n = 0;
nread = getline (&ptr_buf, &n, fileDescriptor);
free (ptr_buf);
}

У кого-нибудь есть идеи?

Сначала я рассказал о версии glib-c, но теперь я могу '

t добраться до 32-битной машины и "обновить" эту библиотеку. Итак, кто-то может обратиться ко мне?

edit: Для ясности, ошибка сегментации предшествует свободному (ptr_buf)

Ответы [ 3 ]

6 голосов
/ 26 февраля 2012
 libroLetto->titolo = (char*) malloc (lung*sizeof(char));
 memset (libroLetto->titolo, 0, sizeof(libroLetto->titolo));

sizeof(libroLetto->titolo) - размер элемента указателя, а не выделенного объекта.Вам нужно: memset(libroLetto->titolo, 0, lung)

Вы также можете проверять возвращаемое значение функции getline при каждом ее вызове, в противном случае strlen может привести к неожиданным результатам.

Последнее, но не менее важное:

lung = strlen (ptr_buf);
libroLetto->autore = (char*) malloc (lung*sizeof(char));

Вы не выделяете место для завершающего нулевого символа, вам нужно: malloc(lung + 1)

0 голосов
/ 17 марта 2012

Вот моя тестовая программа, которая доказывает, что действительно есть проблема.Я также отправил это в Ubuntu, но оно еще не было отправлено:

Вот тестовая программа:


#include        <objc/Object.h>
#include        <dmalloc.h>

main (int argc, char *argv[]) {
  size_t len;
  char *fname;
  char *rootname = "TESTFILE";

  len   = strlen (rootname) + 1;
  fname = (char *) calloc (len,1);

  printf ("rootname=%s len=%d\n", rootname,len);
}

Скомпилировано с этой строкой:

    gcc -o tst tst.m -ldmalloc

и это дает такой результат:

$ ./tst
rootname=TESTFILE len=9
Segmentation fault

0 голосов
/ 26 февраля 2012

Вам не нужно делать все это копирование.Я полагаю, что getline () уже выполняет выделение для вас.

void estrai_libro (FILE* fileDescriptor, Libro* libroLetto) {

char * ptr_buf;
size_t n;

ssize_t nread;

n = 0;
libroLetto->titolo = NULL;
nread = getline ( &libroLetto->titolo, &n, fileDescriptor);

libroLetto->autore = NULL;
n = 0;
nread = getline ( &libroLetto->autore, &n, fileDescriptor);

libroLetto->editore = NULL;
n = 0;
nread = getline ( &libroLetto->editore, &n, fileDescriptor);

libroLetto->data_pubblicazione = NULL;
n = 0;
nread = getline ( &libroLetto->data_pubblicazione, &n, fileDescriptor);

libroLetto->num_pagine = NULL;
n = 0;
nread = getline ( &libroLetto->num_pagine, &n, fileDescriptor);

libroLetto->num_copie = NULL;
n = 0;
nread = getline ( &libroLetto->num_copie, &n, fileDescriptor);

ptr_buf = NULL;
n = 0;
nread = getline ( &ptr_buf, &n, fileDescriptor);
free (ptr_buf);
}

К вашему сведению: до стандартизации c99 readline () уже существовали различные версии readline ().(и распространяется в clc).Они имели слегка отличающиеся сигнатуры функций .Скомпилируйте, по крайней мере, -Wall для проверки несоответствия прототипов функций.

UPDATE: упс, это было getline () и это readline (), но компиляция с максимальными предупреждениями, вероятно, в любом случае хорошая идея.

ОБНОВЛЕНИЕ: getline начался как расширение GNU и был стандартизирован posix в 2008 году.

...