Как Valgrind может получить доступ к номеру строки распределения памяти в скомпилированной программе на C, как я могу сделать то же самое?

Когда я запускаю простую команду Valgrind, такую ​​как ...

valgrind --leak-check=yes ./my_program

... вывод ошибок Valgrind показывает, где в исходном коде было сделано выделение памяти и где оно было освобождено. Как Valgrind может это сделать? Как я мог сделать это сам, в коде программы? Если это поможет, параметры CFLAGS, определенные в моем make-файле GCC для компиляции:

CFLAGS=-c -Wall -Wextra -Wno-unused-parameter -Wno-unused-variable -g -Og -std=c11 -pedantic

Всего 2 ответа


вывод ошибок, который производит Valgrind, показывает, где в исходном коде было выделено место для памяти и где оно было освобождено. Как Valgrind может это сделать?

Когда вы используете valgrind, вы не запускаете свою программу напрямую. Вместо этого valgrind делает это в среде и с помощью средств, которые позволяют ему осуществлять мониторинг в первую очередь. Это включает, но не ограничивается, заменой своих собственных функций выделения для нормальных реализаций стандартной библиотеки. Именно эти альтернативные функции распределения дают Valgrind средства для отслеживания местоположений в двоичном файле, где происходят распределения и освобождения.

Информация, необходимая для связи номеров строк источника с конкретными инструкциями в скомпилированном двоичном файле, является частью отладочной информации, включенной в двоичный файл при компиляции с параметром -g . Если вы опустите -g вы обнаружите, что вывод Valgrind менее информативен в отношении местоположения ошибки.

Как я мог сделать это сам, в коде программы?

Вы также можете предоставить свой собственный malloc т . Д. и free функции. Вы можете использовать их во всей вашей программе вместо версий стандартной библиотеки, хотя детали могут частично зависеть от вашей реализации на Си. Делать это правильно нетривиально, а детали зависят от системы.

Средства, с помощью которых эти функции могут идентифицировать точку, из которой они вызываются, еще более нетривиальны и зависят от системы. Язык C не определяет какую-либо интроспективную функцию, такую, как это требуется, поэтому вам нужно будет предоставить ее самостоятельно.

Стандарт C также не определяет какой-либо способ, которым программа могла бы получить доступ к отладочной информации из своего собственного двоичного файла, ни даже какой-либо надежный способ даже найти свой собственный двоичный файл, ни, в этом отношении, «отладочную информацию». Valgrind имеет явное преимущество перед самой программой в этой области: поскольку valgrind запускает программу, valgrind может знать, какой двоичный файл он запускает.

В общем, тогда ответ таков: если вам нужно задать вопрос в первую очередь, то вы, вероятно, не готовы делать то, что просите вообще. Вместо этого вам следует поискать существующий инструмент, который достаточно близок к тому, что вы хотите (возможно, сам valgrind), или изменить ваши требования. В частности, вам следует подумать о том, предоставляет ли механизм на основе препроцессора, описанный в ответе @ ryyker, средства, позволяющие достаточно приблизиться к тому, что вы имеете в виду.


... номер строки доступа к памяти в скомпилированной программе на C, как я могу сделать то же самое?

Предопределенные макросы, такие как __FILE__ , __FUNCTION__ и __LINE__, могут использоваться в источнике C для вывода информации о том, где что-то происходит. Количество и разнообразие макросов зависят от среды. Например, __FUNCTION__ является расширением и не входит в число предопределенных макросов, указанных стандартом, как указано в комментариях. Вы можете прочитать об использовании макроса GCC и расширениях здесь . (См. Ссылки выше для дополнительных советов по использованию.)

В этом примере эти макросы используются, чтобы показать, в каком файле, функции и в какой строке # происходит событие:

char buf[100];
sprintf(buf, "%p (%s() %s() line# %d)
", malloc(10), __FILE__, __FUNCTION__, __LINE__);
printf(buf);//(Or more likely usage, write to a log file)

Обратите внимание, что в этом примере нет проверки / обработки ошибок, таких как проверка возвращаемого значения для malloc() , что всегда является хорошей идеей.


Есть идеи?

10000