LINUX.ORG.RU

Segfault with MALLOC_CHECK_=0

 , , ,


0

2

Привет всем. Есть проект, в котором потихоньку ковыряюсь. Сейчас запнулся на одном интересном моменте. Определенный кусок кода, в котором присутствует такие вот строки:

 dictionary * dictionary_new(int size)
{
     dictionary  *   d = NULL ;

    /* If no size was specified, allocate space for DICTMINSZ */
    if (size<DICTMINSZ) size=DICTMINSZ ;

    if (!(d = (dictionary *)calloc(1, sizeof(dictionary)))) {
        return NULL;
    }
    printf("d = %p\n", (void *)d);
    d->size = size ;
    d->val  = (char **)calloc(size, sizeof(char*));
    d->key  = (char **)calloc(size, sizeof(char*));
    d->hash = (unsigned int *)calloc(size, sizeof(unsigned));
    return d ;
}                                                  

На строке

    d->val  = (char **)calloc(size, sizeof(char*));

Программа периодически вываливается с :

Program received signal SIGSEGV, Segmentation fault.
malloc_consolidate (av=0xb7eaf440) at malloc.c:4246
4246	malloc.c: No such file or directory.
(gdb) bt
#0  malloc_consolidate (av=0xb7eaf440) at malloc.c:4246
#1  malloc_consolidate (av=0xb7eaf440) at malloc.c:4192
#2  0xb7d8318f in _int_malloc (av=0xb7eaf440, bytes=512) at malloc.c:3532
#3  0xb7d86d46 in __libc_calloc (n=128, elem_size=4) at malloc.c:3274
#4  0xb7f751c0 in dictionary_new (size=128) at src/dictionary.c:129
#5  0xb7f74889 in iniparser_load (ininame=0x804ae32 "../res/bds.ini") at src/iniparser.c:651
#6  0x0804a16b in get_key_number (ini_file=0x0, key

Не могу понять: в чем тут дело. С MALLOC_CHECK_=1 (2 или 3). Все работает. Но, как я понял — там тогда используются другие реализации malloc (более медленные). Сейчас в ступоре: не могу понять в чем именно дело. Или портится где-то сам кусок кучи, где malloc хранит указатели на свои «выделения». Запускал под valgrind, что странно — программа не вылетает. Запускал с

valgrind -v --tool=exp-sgcheck
Получил:
==7061== ERROR SUMMARY: 49 errors from 3 contexts (suppressed: 9 from 7)
==7061== 
==7061== 1 errors in context 1 of 3:
==7061== Invalid read of size 1
==7061==    at 0x419EB8E: vfprintf (vfprintf.c:1624)
==7061==    by 0x42572D8: __vsprintf_chk (vsprintf_chk.c:86)
==7061==  Address 0xbedb00d8 expected vs actual:
==7061==  Expected: stack array «section» of size 1,025 in frame 3 back from here
==7061==  Actual:   stack array «key» of size 1,025 in frame 3 back from here
==7061==  Actual:   is 0 after Expected
==7061== 
==7061== 
==7061== 18 errors in context 2 of 3:
==7061== Invalid read of size 1
==7061==    at 0x419EB8E: vfprintf (vfprintf.c:1624)
==7061==    by 0x42572D8: __vsprintf_chk (vsprintf_chk.c:86)
==7061==    by 0x7320726E: ???
==7061==  Address 0xbedb00a8 expected vs actual:
==7061==  Expected: stack array «section» of size 1,025 in frame 3 back from here
==7061==  Actual:   stack array «key» of size 1,025 in frame 3 back from here
==7061==  Actual:   is 0 after Expected
==7061== 
==7061== 
==7061== 30 errors in context 3 of 3:
==7061== Invalid read of size 1
==7061==    at 0x419EB8E: vfprintf (vfprintf.c:1624)
==7061==    by 0x42572D8: __vsprintf_chk (vsprintf_chk.c:86)
==7061==    by 0x62757472: ???
==7061==  Address 0xbedb00a8 expected vs actual:
==7061==  Expected: stack array «section» of size 1,025 in frame 3 back from here
==7061==  Actual:   stack array «key» of size 1,025 in frame 3 back from here
==7061==  Actual:   is 0 after Expected
==7061== 
--7061-- 
--7061-- used_suppression:      9 ld-2.X possibly applying relocations
==7061== 
==7061== ERROR SUMMARY: 49 errors from 3 contexts (suppressed: 9 from 7)

Хотя, честно, не понял где тут «хорошо» и где «плохо».

Куда дальше копать?

Тебе надо вылечить все «Invalid read». Это 100% ошибки в коде, от того и валится. В 99% случаев это уберёт «подземные стуки» что ты видишь.

И как объявлен dictionary?

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

Спасибо. Вот только бы понять ГДЕ именно этоn vfprintf вызывается. А dict — это структура

typedef struct _dictionary_ {                                                                   
int             n ;     /** Number of entries in dictionary */
int             size ;  /** Storage size */
char        **  val ;   /** List of string values */
char        **  key ;   /** List of string keys */
unsigned     *  hash ;  /** List of hash values for keys */
} dictionary ;

GreenBag ★★
() автор топика
Ответ на: комментарий от GreenBag

Сходу могу посоветовать --gdb-attach=yes . Это запустит дебаггер при ошибке.

Мне вот интересно кто проверяет что calloc вернул корректное значение. У тебя проверка только в одном месте. Точнее пока сказать не могу, на сях уже несколько лет не прогал и вся эта адресная арифметика для меня тёмный лес, но выглядит более-менее корректно. Т.е., я думаю проблема в раздолбанной куче, а не в том месте программы где segfault

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

Спасибо, подрубил опцию (в текущей версии valgrind это --db--attach=yes). Все работает, дебаггер сам не включается.

Мне вот интересно кто проверяет что calloc вернул корректное значение

Я так предполагаю, что где-то в недрах самой libc6. Хотя, это — предположение.

GreenBag ★★
() автор топика
Ответ на: комментарий от GreenBag

Все работает, дебаггер сам не включается.

Т.е. программа работает без сбоев и valgrind ничего не пишет? А можно посмотреть исходники целиком или это коммерческая тайна?

Я так предполагаю, что где-то в недрах самой libc6. Хотя, это — предположение.

не, я не про это. Тебе в коде нужно проверять что память выделилась нормально. Т.е. проверять возвращаемое значение calloc.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

Ну, если Вам таки интересно, я только за (: Ибо кода не то, чтобы и много, но есть. Вот ссылка на git repo.https://github.com/mityaz/nc_bds Куски кода с dictionary — shared либа, подрубаемая отсюда https://github.com/ndevilla/iniparser

GreenBag ★★
() автор топика
Ответ на: комментарий от true_admin

«Грязный» фикс придумал: все вызовы get_key_number() перенес ДО старта всех нитей. Хотя в самых нитях никаких обращений к вышеупомянутым функциям нет.

GreenBag ★★
() автор топика
Ответ на: комментарий от GreenBag

Если вы уже решили собрать это мое поделие, то еще пару слов (:

Есть файл настройки (в res/bds.ini) Он работает на ура со всем, окромя /dev/ttyUSB0 и прочие. Как раз вылатает этот зловещий сегфолт.

И да, чтобы прога работала нужны serial порты. Можно там заэмулировать

socat -d -d pty,raw,echo=0 pty,raw,echo=0

И поменять соответственно на /dev/pts/<номер>

GreenBag ★★
() автор топика
Ответ на: комментарий от true_admin

Кстати, палка в колеса гиту — мне не нужны o. файлы, но пустая папка для них нужна. Если не ошибаюсь, это можно достичть через большую задницу (если не создавать пустого .txt файла в obj, что есть тупостью, как по мне). Но это все так, к слову.

GreenBag ★★
() автор топика
Ответ на: комментарий от true_admin

Ты так исчез, будто там был вызов rm -rf :) Если получится запустить, то будет хорошо. Нет, что ж, тоже ок. Но вопрос но повестке дня у меня остается...

GreenBag ★★
() автор топика
Ответ на: комментарий от GreenBag

rm -rf

ммм, сорри, щас немного занят.

А ты прогонял через проги которые дебажат ошибки в мультипоточных приложениях?

пустая папка для них нужна

увы, бич многих систем контроля версий. Создай таки пустой файл :)

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

Не, не прогонял. Даже не знал о существовании оных.

Да мне не срочно. Сам буду уже завтра в процессе ковырять. «Фикс» есть, пока работает. Но я не люблю такой кривоты. Поэтому буду таки добивать (пытаться) (:

В любом случае, все равно спасибо за участие ;)

GreenBag ★★
() автор топика
Ответ на: комментарий от GreenBag

мне не нужны o. файлы, но пустая папка для них нужна.

Зачем держать в репозитории пустую директорию для объектных файлов? Пропиши в Makefile правило для ее создания при сборке.

Deleted
()
Ответ на: комментарий от Relan

Спасибо за советы. Добавлю правило в Makefile + сейчас буду пробовать с указанными флагами.

GreenBag ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.