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

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

valgrind --leak-check=yes ./my_program

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

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

Ответы [ 2 ]

3 голосов
/ 16 января 2020

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

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

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

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

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

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

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

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

2 голосов
/ 16 января 2020

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...