Подтвердить что ты не робот

Утечка памяти С++

Я просто написал код на С++, который выполняет некоторые манипуляции с строкой, но когда я запускал valgrind, он показывает некоторые возможные утечки памяти. Отладка кода до гранулярного уровня Я написал простую программу на С++, которая выглядит так:

#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
        std::string myname("Is there any leaks");
        exit(0);
}

и запустив valgrind над ним, я получил:

==20943== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 26 from 1)
==20943== malloc/free: in use at exit: 360,645 bytes in 12,854 blocks.
==20943== malloc/free: 65,451 allocs, 52,597 frees, 2,186,968 bytes allocated.
==20943== For counts of detected errors, rerun with: -v
==20943== searching for pointers to 12,854 not-freed blocks.
==20943== checked 424,628 bytes.
==20943== 
==20943== LEAK SUMMARY:
==20943==    definitely lost: 0 bytes in 0 blocks.
==20943==      possibly lost: 917 bytes in 6 blocks.
==20943==    still reachable: 359,728 bytes in 12,848 blocks.
==20943==         suppressed: 0 bytes in 0 blocks.
==20943== Reachable blocks (those to which a pointer was found) are not shown.
==20943== To see them, rerun with: --show-reachable=yes

Затем мне показалось, что мы принудительно вышли (что я также выполнил в своем исходном коде на С++). Теперь проблема в том, что я хочу выйти из программы, так как мой предыдущий старый код ждет статуса выхода нового кода. Например, двоичный файл a.out ожидает статуса выхода b.out. Есть ли способ избежать утечек памяти, или мне действительно нужно беспокоиться об утечке памяти, поскольку программа уже выходит из этой точки.

Это также вызывает у меня другой вопрос, является ли такой код вредным?

#include<stdio.h>
#include<cstdlib>
int main()
{
        char *p=(char *)malloc(sizeof(char)*1000);
        exit(0);
}
4b9b3361

Ответ 1

Если вы настаиваете при использовании exit():

#include<iostream>
int main(){
    {
        std::string myname("Are there any leaks?");
    }
    exit(0);
}

Кроме того, при возврате из main возвращаемое значение становится кодом выхода приложений. Поэтому, если вы хотите передать код выхода, используйте return exitCode; в main() вместо exit.

Относительно этой части:

Это также вызывает у меня другой вопрос, является ли такой код вредным?

Да, потому что это привычка программирования BAD.

ОС очистит любую память, которую вы не смогли отпустить, поэтому пока вы не успели съесть всю системную память и файл страницы, вы не должны повредить ОС.

Однако при написании неаккуратного/негерметичного кода может появиться привычка, поэтому полагаться на ОС для очистки вашего беспорядка - это плохая идея.

Ответ 2

Используйте return 0; вместо exit(0); в конце main. Использование exit обходит выполнение деструкторов.

Ответ 3

Это также вызывает у меня другой вопрос, является ли такой код вредным?

#include<stdio.h>
int main()
{
        char *p=(char *)malloc(sizeof(char)*1000);
        exit(0);
}

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

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

Ответ 4

В большинстве случаев он стоит очистить после себя, по многим уже обоснованным причинам: улучшенная ремонтопригодность, лучшая утилита от инструментов проверки и т.д.

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

В некоторых случаях, однако, может быть лучше просто выйти и "утечка".

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

Рассмотрим большой связанный список, где каждый node динамически распределяется и несет существенную динамически распределенную структуру. Чтобы очистить это, вы должны посетить каждый node и освободить каждую полезную нагрузку (что, в свою очередь, может привести к прохождению других сложных структур).

Вы можете выполнить миллионы операций с памятью для выполнения такой структуры.

Пользователь хочет выйти из вашей программы, и они сидят там в течение 10 секунд, ожидая, когда произойдет куча нежелательной обработки. Они не могут быть заинтересованы в результате - они все-таки покидают программу.

Если вы допустили эту "утечку", операционная система может быстрее вернуть весь блок памяти, выделенный вашему процессу. Он не заботится о структурах и очистке любого объекта.

http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx

В конечном счете вы должны понимать, что говорят вам ваши инструменты, чтобы убедиться, что вы правильно их используете.

Ответ 5

Чтобы избежать утечки памяти, верните статус из main вместо вызова exit. Если вы возвращаете нуль, вы можете опустить оператор return, если хотите; программа выйдет со статусом нуля в этом случае.

Это также вызывает у меня другой вопрос, является ли такой код вредным?

В современной операционной системе это не причинит никакого вреда - все ресурсы будут исправлены автоматически, когда программа завершится. Тем не менее, это затрудняет использование таких инструментов, как Valgrind, чтобы найти настоящие проблемы, поэтому лучше всего избегать даже безвредных утечек памяти, если сможете.

Ответ 6

#include<iostream>
using namespace std;
int main()
{
    {
        std::string myname("Is there any leaks");
    }
    exit(0);
}

Ответ 7

В то время, когда ваш процесс фактически завершается, как при выходе main(), ОС будет восстанавливать все ресурсы, назначенные вашему приложению в любом случае. Как вы выходите не так важно - по крайней мере, в отношении динамической памяти.

Если у вас открыто какое-то распределенное подключение к базе данных, вы должны использовать обработчики atexit(), чтобы закрыть его, а принудительное завершение с прямым выходом может заставить их не запускать, что было бы плохо, но в отношении ресурсов вашей ОС что вы, вероятно, все в порядке.

Вы также должны всегда следить за тем, чтобы вы открывали (вручную) блокировки файлов и другие подобные вещи, поскольку они могут не исчезнуть из-за выхода из процесса.

Ответ 8

Если вы хотите разорвать выполнение и передать код возврата без превышения деструкторов, выведите исключение и извлеките возвращаемое значение из исключения в main().

Ответ 9

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

Ответ 10

Чтобы добавить другое мнение.

Такой код не вреден всем. ОС будет заботиться обо всем, когда процесс завершается. Все остальное приводит к нестабильной ОС. Просто убедитесь, что ваши постоянные данные (файлы,...) согласованы.

Чтобы идти немного дальше и провокационно заявляет, что явное освобождение памяти при выходе из программы может быть вредным.

  • Выход программы занимает больше времени (вы когда-нибудь раздражались, ожидая выхода программы, пока компьютер не выключится?)
  • Правильный порядок уничтожения не всегда тривиален, особенно с сторонними компонентами (я помню некоторые программы, которые, вероятно, сбой при выходе)
  • OS не может позволить вам освободить память после выхода из main (*) и вместо этого убить вашу программу

Вы рискуете этим только для того, чтобы Valgrind дал вам определенный результат? (**)


(*)

#include<iostream>
using namespace std;
std::string myname("Is there any leaks");
int main() {
        exit(0);
}

(**) Ну, конечно, выход любого анализатора памяти более полезен без "шума". Что же касается явного освобождения памяти при выходе в режиме отладки?