heisenbug near printf
От: citrin Россия http://citrin.ru/
Дата: 11.02.13 14:13
Оценка:
При использовании bgpdump столкнулся с тем, что bgpdump -M на некоторых файлах выводит мусор. При этом сами файл не битые, и показываются через bgpdump -m.

Из того, что вижу — до printf (bgpdump.c:1702) доходят валидные данные, но при их выводе возникает мусор, например:

TABLE_DUMP_V2|12/28/12 06:00:15|A|87.226.134.28|1238е⌠(&<
(&<
(4.0/24|2914 7473 375ж©©Hж©©Ьв

На разных файлах мусор выглядит по разному — строка может оборваться в любом месте. Бывает и в самом начале:

TABLE_DUMPПу©©0/13ХВ (е⌠(<
(+(34.38|12389|223.255.`ж©©╗ж©©Ьв
(Ь╓(Ж(└ж©©Ю

Почти при любых попытках изменить printf баг исчезает и данные выводятся без мусора. Достаточно например в конец format добавить пробел и баг перестает воспроизводиться. Или после "плохого" printf можно вставить printf("\n") и баг тоже перестает воспроизводиться.

Никто с подобным не сталкивался?

В курсе что при не соответствии формата и типа данных процесс может упасть в корку, но тут ошибка вроде только в использовании %d вместо %u дляe->prefix_length (u_char) и замена на %u проблему не лечит.
Re: heisenbug near printf
От: citrin Россия http://citrin.ru/
Дата: 11.02.13 16:13
Оценка:
Здравствуйте, citrin, Вы писали:

C>При использовании bgpdump столкнулся с тем, что bgpdump -M на некоторых файлах выводит мусор. При этом сами файл не битые, и показываются через bgpdump -m.


C>Из того, что вижу — до printf (bgpdump.c:1702) доходят валидные данные, но при их выводе возникает мусор


Обнаружил в bgpdump.c строчки:

// more efficient then line buffering
char buffer[16000];
setbuffer(stdout, buffer, sizeof buffer);


Вставил между ними
memset(buffer, 0, sizeof buffer);


и мусор исчез, по крайней мере на тех данных, на которых был раньше.
Re[2]: heisenbug near printf
От: citrin Россия http://citrin.ru/
Дата: 11.02.13 17:28
Оценка: 1 (1)
C>Обнаружил в bgpdump.c строчки:

C>
C>// more efficient then line buffering
C>char buffer[16000];
C>setbuffer(stdout, buffer, sizeof buffer);
C>


C>Вставил между ними

C>
C>memset(buffer, 0, sizeof buffer);
C>


C>и мусор исчез, по крайней мере на тех данных, на которых был раньше.


Точнее не так, я проверял на
static char buffer[16000]; + memset
и похоже результат дало именно объявление буфера как static а не memset. memset буз static похоже не помогает.
Re[3]: heisenbug near printf
От: dilmah США  
Дата: 11.02.13 19:16
Оценка:
C>и похоже результат дало именно объявление буфера как static

ну, он же теперь разместил его в другой области памяти.
Значит где-то кто-то портит память, проявлялось в порче буфера.
Re[4]: heisenbug near printf
От: citrin Россия http://citrin.ru/
Дата: 11.02.13 20:41
Оценка: 1 (1)
Здравствуйте, dilmah, Вы писали:


C>>и похоже результат дало именно объявление буфера как static


D>ну, он же теперь разместил его в другой области памяти.

D>Значит где-то кто-то портит память, проявлялось в порче буфера.

Насколько понимаю происходит так:

1. Если буефер объявлен без static то он аллоцируется на стеке. К моменту завершения main() в буфере могут быть данные — их flush-ит libc уже после завершения main, когда стек от main может быть уже использован повторно. Собственно по этому добавление пробела в format маскировало баг — объем выводимых данных увеличивался и буфер успевал flush-ится до завершения main().

2. Если буфер объявлен как static, то под него резервируется место в секции .bss и данные остаются доступны и после завершения main.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.