Подавление ошибок GTK в Valgrind

Я пытаюсь написать приложение GTK и хочу проверить его действительность с помощью valgrind.

Это пример программы, которую я хочу протестировать:

#include <stdio.h>
#include <stdlib.h>

#include <gtk/gtk.h>

int
main (int argc, char *argv[])
{
  GtkWidget *win;
  GtkWidget *btn;

  gtk_init (&argc, &argv);

  win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  btn = gtk_button_new_with_label ("Hello");

  gtk_container_add (GTK_CONTAINER (win), btn);
  gtk_widget_show_all (win);

  gtk_main();
}

Фонд GNOME написал статью о тестировании приложений с помощью valgrind, но даже если я начну valgrind со всеми этими флагами

valgrind --tool=memcheck --leak-check=full --num-callers=15 --log-file=vgdump ./diashow 

или даже с файлом gtk.suppression, упомянутым на этой странице valgrind

valgrind --tool=memcheck --leak-check=full --num-callers=15 --suppressions=gtk.suppression --log-file=vgdump ./diasho

файл дампа valgrind (pastebin) vgdump практически не читается. 2285 строк!

Самым странным для меня является то, что мой файл vgdump начинается с Invalid write of size 4, а затем с Invalid read of size 4. Может ли кто-нибудь мне что-нибудь объяснить?


person schaeferpp    schedule 28.06.2015    source источник


Ответы (1)


По моему опыту, хорошее правило при работе с valgrind - сначала проверить несколько ошибок, попытаться исправить их и снова перезапустить приложение под valgrind. Причина: предположим, у вас есть ошибка в функции, которая выделяет массив и вызывает другую функцию с массивом и размером массива + 1 (т.е. размер на один элемент больше реального размера) . Затем, когда следующая функция попытается получить доступ к этому избыточному элементу, valgrind может заметить это и вызвать предупреждение. Но функция может вызвать другую функцию, которая также может попытаться получить доступ к элементу, что также приведет к предупреждению и так далее.

Таким образом, вы получаете кучу сообщений, которые приводят к единственной ошибке. И даже если есть сообщения о другой ошибке, найти их обычно бывает так сложно, что легче исправить первую ошибку и снова перезапустить приложение и valgrind.

Также вам нужно относиться к ошибкам valgrind с долей скептицизма. Например. Я помню, как он однажды сообщил мне о неинициализированной переменной в функции main - по какой-то причине valgrind не мог понять, что это действительно так. Это привело к сообщению об использовании неинициализированной переменной в каждой функции, которую вызывает main, то есть в каждой функции в моей программе. Но я должен упомянуть, что это было давно - три года назад - и я могу предположить, что valgrind не была последней версией даже тогда только потому, что в репозитории Ubuntu, как правило, нет последних версий многих приложений.

Invalid read of size 4 означает где-то переполнение буфера. Трассировка стека первой такой ошибки должна указать, где вы можете найти проблему. Трудно сказать больше, поскольку вы не показывали трассировку стека, но вы должны знать, что функция с ошибкой может быть жертвой неправильного массива сверху.

В качестве примечания я бы посоветовал вам отлаживать такие ошибки с помощью AddressSanitizer, который по умолчанию доступен как для GCC, так и для Clang (и у них есть одинаковые параметры для его включения). Он имеет тенденцию давать гораздо более подробный вывод об ошибке (ура, он даже красочный! Ε :), и по умолчанию закрывает приложение при любой ошибке памяти произошел. Более того, valgrind пропускает большинство ошибок памяти, когда AddressSanitizer этого не делает - например, переполнение стека и т. Д. Да, иногда (как в вашем случае) это работает, но по моему опыту не очень довольно часто.

person Hi-Angel    schedule 28.06.2015
comment
Спасибо за объяснение. - Но я вставил stacktrace (я думаю, вы имеете в виду valgrind-warnings?) Как связанный pastebin-url . Главный вопрос: почему gtk генерирует переполнение стека в такой тривиальной программе? - person schaeferpp; 28.06.2015
comment
@pausch ах, извини, я не понял. Хорошо, трассировка стека действительно не очень полезна, как я вижу. Знак вопроса - это функции где-то в библиотеке, которые, скорее всего, являются жертвой, но больше сказать сложно. Хорошо, вы знаете, просто скомпилируйте свое приложение с -g3 -fsanitize=address параметрами, затем запустите его и посмотрите, не упадет ли оно. Если это не так, просто игнорируйте предупреждение (скептицизм, помните?), потому что я на самом деле не знаю случая, когда дезинфицирующее средство адреса пропустит ошибку, чего нет у valgrind, но я ' Мы видели случаи с ложными сообщениями valgrind. - person Hi-Angel; 28.06.2015
comment
Я пробовал эти параметры компиляции, но после их установки (проверено с помощью gcc и clang) valgrind не запускается: Shadow memory range interleaves with an existing memory mapping. ASan cannot proceed correctly. ABORTING. - person schaeferpp; 28.06.2015
comment
@pausch hm… На странице часто задаваемых вопросов упоминается возможное решение, которое может работать, а может и не работать. Попробуйте запустить свое приложение, например, LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.0 ./myapp (но убедитесь, где находится библиотека, прежде чем делать это. Вы можете просто запустить locate asan, чтобы вывести список файлов с «asan» в именах). - person Hi-Angel; 28.06.2015
comment
@pausch, подождите, я только что перечитал ваш комментарий, вы сказали «valgrind не запускается»? Нет-нет, я не это имел в виду - вы должны запустить приложение, скомпилированное с параметрами, без valgrind. И если есть ошибки памяти, очиститель адресов просто убьет ваше приложение сообщением об ошибке. В противном случае я бы посчитал сообщения valgrind ложными (хотя для уверенности я бы спросил в списке рассылки valgrind) - person Hi-Angel; 28.06.2015
comment
Очень странно: я пробовал с LD_PRELOAD=/usr/lib/libasan.so, потому что в моей системе указанный вами путь не существует. Но при выполнении LD_PRELOAD=/usr/lib/libasan.so ./diashow я получаю сообщение Your application is linked against incompatible ASan runtimes. - person schaeferpp; 28.06.2015
comment
Ага. Что предыдущая ошибка произошла от valgrind. См. Следующие снимки экрана. Вызов Valgrind с libasan +++ За исключением моего Makefile, но изменение clang на gcc ничего не меняет ++++ Вызов с помощью LD_PRELOAD - person schaeferpp; 28.06.2015
comment
@pausch, ладно, звонить с valgrind в любом случае не имело бы смысла. Ошибка LD_PRELOAD действительно странная. Я бы попытался скомпилировать его, статически связав libasan, это можно сделать, добавив LDFLAGS -Wl,-Bstatic -lasan -Wl,-Bdynamic. Но я должен упомянуть это еще раз: если приложение, скомпилированное с помощью средства очистки адресов, работает без valgrind - это в значительной степени вам нужно знать, здесь нет причин заставлять его работать с valgrind. - person Hi-Angel; 28.06.2015
comment
Извините за мою лень: я не понимал, что libasan - это тот вид AddressSanitizer, о котором вы упомянули. Итак, если я вызываю свою программу, которая скомпилирована с этими флагами, libasan выводит сообщения об ошибках, если у меня есть ошибки при доступе к памяти? - person schaeferpp; 28.06.2015
comment
@pausch да, он выводит ошибку, а затем убивает приложение. По моему опыту, это работает при любом неправильном доступе к памяти (переполнение буфера, доступ к освобожденной памяти и т. Д.). - person Hi-Angel; 28.06.2015
comment
Я только что протестировал AddressSanitizer на очень дамп-минимальную программу с ошибкой памяти, и это отлично работает. Он также работает только с опцией -fsanitize=address. Спасибо! Последний вопрос: если valgrind сообщает об ошибках в gtk, которые AddressSanitizer не находит, могу ли я тогда игнорировать сообщение valgrind? - person schaeferpp; 28.06.2015
comment
@pausch, несмотря на то, что все в порядке, я бы все равно спросил в списке рассылки valgrind, чтобы убедиться. Смотрите: Я почти уверен, что если есть ошибка в самой библиотеке Gtk, средство очистки адресов ничего не скажет, потому что это не ваше приложение. Но я не помню, как работает valgrind, и теоретически могу предположить, что ошибки не такие уж ложные, а скорее неправильный доступ к памяти в самой библиотеке. Но это всего лишь мысль, которая может быть ошибочной, и valgrind действительно иногда сообщает о ложных ошибках (по крайней мере, это часто случалось в прошлом) - поэтому я бы все равно спросил в их списке рассылки. - person Hi-Angel; 28.06.2015
comment
@pausch, но отвечая, не могли бы вы проигнорировать это - да, даже если в самой библиотеке Gtk действительно есть ошибка, вы ничего не можете с ней поделать (хотя вы всегда можете скачать исходный код и помочь в разработке FOSS ;)). - person Hi-Angel; 28.06.2015