2016-09-08 4 views
1

В моей программе на C у меня много структур данных, которые динамически выделяют память. Если пользователь делает любой из следующих действий:Очистка, когда пользователь заставляет мою программу выйти?

  • Alt-F4

  • клик на X

  • Force завершает работу с помощью диспетчера задач, и т.д.

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

ответ

4

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

Во-первых, ОС автоматически освободит всю память, связанную с вашим процессом, когда она будет завершена. Вам никогда не придется беспокоиться о том, что оставшаяся RAM остается.

Во-вторых, вы можете получить уведомление по Alt-F4/закрытии окна. Я не знаю деталей, никогда не писал GUI-приложение для Windows, но должен быть каким-то образом вы можете организовать его обработать так же, как выбрать «Выход» из меню приложения; ваш «инструментарий» может даже сделать это для вас по умолчанию. Правильное использование этого уведомления - это сохранение файлов на диск и чистое отключение сетевых диалогов. (ОС будет также автоматически закрыть все файловые дескрипторы и разъединение все сетевые розетки, но это не будет вымывать несохраненные изменения для вас, и не будет посылать на уровне приложений сообщения прощай.)

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


Как обсуждалось в комментариях: да, это означает, что не нужно освобождать память вручную перед выходом. Фактически, это более эффективный, если вы не, как обсуждалось here и here. «Общая мудрость», в которой требуется ручное освобождение, относится к началу микрокомпьютеров; (некоторые итерации) CP/M и MS-DOS действительно нуждались в каждом приложении для освобождения памяти вручную; в настоящее время это пример cargo-cult programming.

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

+0

Это действительно интересно, потому что, если то, что вы говорите, правда, тогда я был введен в заблуждение. Я думал, что если вы создали программу, имеющую только одну строку: 'int main() {long * x = malloc (sizeof (long)); return 0}; 'и если вы запустили эту программу достаточно раз, ваш компьютер в конечном итоге исчерпал бы память. Если это ложь, то почему все программы на C я смотрю на выделение памяти перед любым закрытием? Если ОС сделает это для меня, то зачем мне тратить столько времени на вызов 'free()' на каждую глобальную переменную, на которую я выделил память? – Hatefiend

+0

@Hatefiend Вам не только не нужно, это может быть намного эффективнее, если вы этого не сделаете, как обсуждалось [здесь] (https://stackoverflow.com/questions/231089/freeing-in-an-atexit#242317) и [здесь] (https://blogs.msdn.microsoft.com/oldnewthing/20120105-00/?p=8683). В любом случае, это хорошая причина сделать это, но только в отладочных сборках: инструменты, которые обнаруживают утечки памяти _genuine_ (где процесс, если он будет работать навсегда, будет потреблять все больше и больше памяти навсегда), вам нужно это сделать. – zwol

+0

@ Hatefiend «Осторожно освободить всю память до выхода» - это случай [апокрифических пяти обезьян и лестницы] (http: //www.throwcase.com/2014/12/21/that-five-monkeys-and-a-banana-story-is-frbish /): он должен использоваться в дни CP/M и MS-DOS и продолжает оставаться преподается как «лучшая практика», хотя это не только не требуется, но и практическая практика. – zwol

2

Вы можете зарегистрировать функцию, которая будет вызываться при выходе, с atexit. Это должно обрабатывать нормальное завершение (путем возврата от main или вызова exit в любом месте программы) и Alt + f4 и нажатия на X тоже. Тем не менее, ваша программа не может делать, когда она убита (принудительное завершение в диспетчере задач). К счастью, большинство современных операционных систем могут и могут очищать память, используемую вашей программой, даже когда она умирает от неестественных причин.

Ниже приведен пример программы, использующей atexit. Программа создает (или обрезает) файл с именем atexit.txt. Когда программа завершается нормально, она записывает Exited! в этот файл и закрывает дескриптор.

#include <stdlib.h> 
#include <stdio.h> 

FILE * quitFp; 

void onExit(){ 
    fputs("Exited!", quitFp); 
    fclose(quitFp); 
} 

int main(){ 
    quitFp = fopen("atexit.txt", "w+"); 
    if(!quitFp){ 
     return 1; 
    } 

    atexit(onExit); 

    puts("Press enter to exit"); 

    getchar(); 
    return 0; 
} 

В Windows 8.1, собранный с MinGW/GCC это работает для нормальной return и exit и когда я нажимаю X в окне консоли.

+0

Будет ли функция, которую я укажу с помощью ' atexit' вызываться, когда я лично вызываю 'exit (0) 'или' return 0'? – Hatefiend

+0

@Hatefiend, да это будет – Kninnug

+0

Другой вопрос, если пользователь отключил электроэнергию, выключает компьютер или принудительно выключает компьютер, утечки памяти даже не имеют значения в этой точке? Поскольку ОЗУ очищается, когда компьютер загружается? – Hatefiend

Смежные вопросы