Утечки с помощью makefile

#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;
}