1

In my C program, I have many data structures that are dynamically allocating memory. If the user does any of the following:

  • Alt-F4

  • Clicks on the X

  • Force quits via Task Manager, etc

then my program will have a memory leak. How do I do a set on close request feature so I can clean up my global variables before my program is shut down unnaturally?

Biffen
  • 6,249
  • 6
  • 28
  • 36
Hatefiend
  • 3,416
  • 6
  • 33
  • 74

2 Answers2

4

(Your terminology strongly suggests a Windows-specific application so I have written this answer accordingly. On other modern operating systems, the terminology is different, but the behavior is the same, except for some embedded environments, but if you were coding for those you would not have asked this question.)

First, the OS will automatically deallocate all memory associated with your process when it is terminated. You never have to worry about RAM remaining allocated.1

Second, you can get notified upon Alt-F4 / window close. I don't know the details, never having written a GUI application for Windows, but there should be some way you can arrange to get it treated the same as selecting Quit from the application's menus; your "toolkit" might even do this for you by default. The proper use of this notification is to save files to disk and cleanly shut down network dialogues. (The OS will also automatically close all file handles and disconnect all network sockets, but it won't flush unsaved changes for you, nor will it send application-layer goodbye messages.)

Third, you cannot receive a notification upon "force quit", and this is by design, because it's the software equivalent of the big red emergency stop button on an industrial robot -- it's for situations where making the process go away right now, no matter what is more important than any potential data loss. As you can't do anything about this, you should not worry about it.


1 As discussed in the comments: yes, this means it is not necessary to deallocate memory manually before exiting. In fact, it is more efficient if you don't, as discussed here and here. The "common wisdom" that manual deallocation is required dates to the early days of microcomputers; (some iterations of) CP/M and MS-DOS did indeed need each application to deallocate memory manually; nowadays it is an instance of cargo-cult programming.

That said, there are some good reasons to deallocate memory manually before exiting. The most obvious is that some leak-detection tools need you to do it, because they do not know the difference between "memory that the application could have freed if it had bothered" and "memory that the application has lost all valid pointers to, and cannot free anymore". A less obvious case is if you are writing a library, or there's a possibility that your application might get turned into a library in the future. Libraries need to be able to manually free all of their allocations upon request by the application, because the application might need to set up, use, and tear down the library many times in the lifetime of one process. (However, it will be more efficient if the application sets up the library once in its lifetime, uses it repeatedly, and then doesn't bother tearing it down before exiting.)

zwol
  • 135,547
  • 38
  • 252
  • 361
  • That's really interesting because if what you say is true, then I have been misled. I thought that if you made a program that had only one line: `int main() { long *x = malloc(sizeof(long)); return 0 };` and if you ran that program enough times, your computer would eventually run out of memory. If that is false, then why all the C programs I look at de-allocate the memory before any kind of shut down? If the OS will do it for me, then why do I need to spend so much time calling `free()` on every global variable that I allocated memory to? – Hatefiend Sep 08 '16 at 20:49
  • @Hatefiend Not only do you not need to, it can be much more efficient if you don't, as discussed [here](https://stackoverflow.com/questions/231089/freeing-in-an-atexit#242317) and [here](https://blogs.msdn.microsoft.com/oldnewthing/20120105-00/?p=8683). There _is_ a good reason to do it anyway, but only in debug builds: tools that find _genuine_ memory leaks (where the process, if left running forever, will consume more and more memory forever) need you to do it. – zwol Sep 09 '16 at 13:33
  • @Hatefiend "Carefully free all memory before exiting" is a case of the [apocryphal five monkeys and a ladder](http://www.throwcase.com/2014/12/21/that-five-monkeys-and-a-banana-story-is-rubbish/) effect: it _used_ to be necessary in the days of CP/M and MS-DOS, and continues to be taught as "best practice" even though it is not only no longer required but a _bad_ practice. – zwol Sep 09 '16 at 13:35
  • http://stackoverflow.com/questions/654754/what-really-happens-when-you-dont-free-after-malloc – David Ranieri Sep 09 '16 at 14:34
2

You can register a function to be called at exit, with atexit. This should handle normal termination (by returning from main or a call to exit anywhere in the program) and Alt+f4 and clicking the X too. However, there is nothing your program can do when it is killed (force quit in the task manager). Fortunately, most modern operating systems can and do clean up the memory used by your program, even when it dies of non-natural causes.

Here is an example of a program using atexit. The program creates (or truncates) a file called atexit.txt. When the program is terminated normally it writes Exited! to that file and closes the handle.

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

On Windows 8.1, compiled with MinGW/GCC it works for normal return and exit and when I click the X on the console window.

Kninnug
  • 7,992
  • 1
  • 30
  • 42
  • Will the function that I specify with `atexit` be called when I personally call`exit(0)` or `return 0`? – Hatefiend Sep 08 '16 at 19:42
  • @Hatefiend, yes it will – Kninnug Sep 08 '16 at 19:49
  • Another question, if the user has a power outage, shuts down his computer, or force shuts down his computer, memory leaks don't even matter at that point right? Since the RAM is flushed when the computer boots up? – Hatefiend Sep 08 '16 at 19:54
  • @Hatefiend When power goes off memory leak is the least of your concerns. So yes, it doesn't matter. – P.P Sep 08 '16 at 20:11
  • @Hatefiend when your program has ended (by whatever cause) all the memory it used is released. When an operating system is rebooted all previous memory allocations become irrelevant so you don't have to worry about that at all. However, I get the feeling you're not so much worried about memory leaks, but rather data leaks. In that case you should know that calling `free` on a buffer releases the memory, but doesn't blank it out beforehand. If you need to protect the data in memory against snooping you should explicitly zero or otherwise remove the data as well. – Kninnug Sep 08 '16 at 20:11
  • @Kninnug Then... there's no need to `free()` all of my global variables upon my program being closed? Why do I see so many people doing it then? – Hatefiend Sep 08 '16 at 20:51