#c #makefile
Вопрос:
Я новичок в программировании на C и столкнулся с проблемой с valgrind, вот мой код :
#include <stdio.h>
int main(int argc,char **argv)
{
printf("Hello World ");
}
Когда я создаю файл Makefile для его запуска :
run: compile
./a.out
compile:
gcc test.c
Я запускаю с valgrind make , и у меня есть ошибка , которая сказала мне, что все еще доступны блоки,
когда я компилирую без файла Makefile, у меня 0 ошибок, может ли кто-нибудь помочь мне решить ее ?
Комментарии:
1. вы собирались
return 0;
это сделать ?gcc
также будет компилировать всевозможные вещи, если у вас их нет, по крайней мере, предупреждайте с помощью таких флагов, как-Wall
; есть много доступных опций для предупреждения или ошибок при возникновении проблем!2. Что, если ты побежишь
./a.out
с Вальгриндом? Похоже, вы улавливаете утечки вmake
самой программе3. Обратите также внимание, что выделение памяти, все еще доступной при завершении программы, само по себе не является утечкой памяти, и обычно это не вызывает особого беспокойства.
4. Ты не можешь убежать
valgrind make
. Я никогда не понимал, почему люди создают цели в файлах создания; не проще ли просто запустить команду напрямую?run
В любом случае, если вы хотите это сделать, вам нужно будет создатьvalgrind
цель, которая запускает вашу программу в valgrind, вот так:valgrind: compile ; valgrind ./a.out
теперь вы можете запуститьmake valgrind
5. Тогда вам не о чем беспокоиться (кроме правильного использования инструмента).
Ответ №1:
Я могу воспроизвести вашу проблему, если запущу
valgrind make
но не в том случае, если я побегу
make compile
valgrind ./a.out
Первый тестирует совершенно другую вещь (использование памяти make
), чем второй (использование памяти ./a.out
).
Как и @MadScientist, я действительно не понимаю, почему люди создают простые run
цели, но для меня имеет смысл, что они создали цель для тестирования с помощью valgrind. Если бы вам нужна была такая цель, то она выглядела бы примерно так (в свете остальной части файла Makefile):
leakcheck: compile
valgrind ./a.out
Комментарии:
1. Просто чтобы закрыть цикл: как говорит Джон в комментариях выше, нет проблем, если ваша программа сообщает об использовании памяти при выходе. Операционная система всегда будет возвращать всю эту память в любом случае, когда ваш процесс завершится. Единственное, что освобождает всю эту память перед выходом, — это усложняет завершение работы вашей программы и делает ее более длительной. Я знаю, что некоторые люди не согласны, но они не правы :). Если у вас есть УТЕЧКИ (то есть несвязанная и несвободная память), это плохо. Если у вас есть ссылка, но не освобожденная память, это нормально. Все инструменты GNU используют этот подход, FWIW.
Ответ №2:
В некоторых системах стандартный уровень ввода-вывода языка программирования C выделяет буферы, которые valgrind сообщает как доступные даже для крошечных программ, таких как ваша.
Я использовал системы, в которых это имеет место. Чтобы освободить стандартные ресурсы ввода-вывода , вы можете закрыть стандартные потоки ввода-вывода перед возвращением main
, как описано в Описании C99 7.21.5.1 fclose
Успешный вызов функции fclose приводит к сбросу потока, на который указывает поток, и закрытию связанного файла. Любые неписаные буферизованные данные для потока доставляются в среду хоста для записи в файл; любые непрочитанные буферизованные данные удаляются. Независимо от того, выполняется вызов или нет, поток отсоединяется от файла, и любой буфер, установленный функцией setbuf или setvbuf, отсоединяется от потока (и освобождается, если он был автоматически выделен).
Заключенное в скобки замечание в конце этого абзаца является подсказкой.
int main(int argc, char **argv) {
/* ... */
fclose(stdin);
fclose(stdout);
fclose(stderr);
return 0;
}