Как избежать утечки памяти, когда пользователь нажимает Ctrl + C под Linux? - PullRequest
6 голосов
/ 26 января 2011

В моей программе, написанной на C и C ++, я создаю объект для выполнения задачи, затем удаляю объект.

В момент после создания нового объекта, но до удаления объекта, если пользователь нажимает ctrl + c , чтобы прервать процесс, это приведет к тому, что удаление не будет вызвано и утечка памяти происходит.

Что я должен сделать, чтобы избежать этой ситуации?

Кроме того, если память была восстановлена ​​ОС, как насчет открытых файлов? Они закрыты операционной системой или я должен закрыть их вручную?

Ответы [ 7 ]

7 голосов
/ 26 января 2011

Нажатие Ctrl C отправит SIGINT процессу, который по умолчанию выполняет в основном упорядоченное завершение работы, включая отключение диспетчера памяти и освобождение всей выделенной кучи истек.Если вам нужно выполнить другие задачи, вам нужно установить обработчик SIGINT и выполнить эти задачи самостоятельно.

7 голосов
/ 26 января 2011

В системе на основе виртуальной памяти вся память возвращается в ОС после завершения процесса, независимо от того, была ли она явно освобождена в коде приложения.Однако то же самое может не относиться к другим ресурсам, которые вы, возможно, захотите освободить чисто.В этом случае вам нужно предоставить пользовательский обработчик сигнала для сигнала SIGINT (который принимается по Ctrl + C), см., Например, http://linux.die.net/man/2/sigaction.

3 голосов
/ 26 января 2011

Если вы выделили какие-либо сегменты совместно используемой памяти SYSV с помощью shmget(2), вы должны очистить себя с помощью shmctl(2).

Если вы выделили какие-либо сегменты разделяемой памяти POSIX с помощью shm_open(3), вы должны очистить себя с помощью shm_unlink(3).

И сегменты разделяемой памяти SYSV и POSIX сохраняются после завершения процесса. Вы можете увидеть, что сохраняется с помощью инструмента ipcs(1).

Конечно, если вы не использовали какие-либо сегменты разделяемой памяти SYSV или POSIX, то это всего лишь шум. :)

2 голосов
/ 26 января 2011

Если процесс завершится, утечка памяти обычно НЕ произойдет.

Большая часть выделенной памяти будет освобождена с помощью Ctrl + C.Если вы видите, что использование памяти не возвращается к своему предыдущему уровню, это почти наверняка вызвано буферизованными блоками файловой системы.

Однако вам определенно следует все исправить, особенно если вы использовали какие-либо другие типы ресурсов:

  • Файлы, созданные во временных каталогах, не будут удалены.Это включает / dev / shm, поэтому такой файл можно считать «утечкой памяти».
  • Сегменты разделяемой памяти System V или posix не будут выброшены при выходе из процесса.Если это вас беспокоит, очистите их специально.Либо очистите их при последующем запуске.

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

Представьте себе процесс, который запускается каждые 5 минут из «cron», если он вылетает при каждом запуске и оставляет некоторый беспорядок, он все еще в порядке, если каждый запуск очищает беспорядок из предыдущего сбоя.

2 голосов
/ 26 января 2011

При нажатии CTRL + C на консоли Linux сигнал SIGINT отправляется приложению, которое, если сигнал не имеет обработчика, завершает программу, возвращая всю память в ОС.Это, конечно, сделает бессмысленным любое освобождение памяти, поскольку вся память будет освобождена после того, как программа существует.Однако, если вы хотите обработать сигнал CTRL + C SIGINT (возможно, записать некоторые последние данные в файл или выполнить другую очистку), вы можете использовать функцию signal(), чтобы установить функцию, которая будет вызываться при сигналеполучено.Посмотрите справочную страницу для этой функции, если вы хотите узнать больше.

1 голос
/ 26 января 2011

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

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

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

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

Примечание

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

1 голос
/ 26 января 2011

ОС вернет память, выделенную процессом, когда процесс завершится в результате нажатия Ctrl-C или любым другим способом.

...