5

Lets say I created a program in c/c++, where I manually allocated some variables. Then while running the program, I send an interrupt signal (Ctrl-C). Are those variables freed from memory, or will they take up space until the system shuts down?

Also, what if I just created integers that weren't manually allocated, do those variable reside, or do they get deleted immediately.

I'm thinking allocated variables will remain, and regular variables will get deleted (because of the stack). If that is the case, is there any way to free the allocated variables from memory after the program has stopped?

Just curious. :)

  • 1
    No, the OS reclaims the memory once the process exits. If it didn't do that, it would be one crappy OS. – Faheem Mitha Apr 8 '16 at 16:13
  • Are you talking about what happens if the process is killed because it didn't handle the signal? – cjm Apr 8 '16 at 16:35
  • Yeah, that was what I was referring to. – alanxoc3 Apr 9 '16 at 15:23
8

Processes are managed by the kernel. The kernel doesn't care how the programmer allocates variables. All it knows is that certain blocks of memory belong to the process. The C runtime matches C memory management features to kernel features: automatic variables go into a memory block called “stack” and dynamic storage (malloc and friends) go into a memory block called “heap”. The process calls system calls such as sbrk and mmap to obtain memory with a granularity of MMU pages. Inside those blocks, the runtime determines where to put automatic varibles and dynamically allocated objects.

When a process dies, the kernel updates its memory management table to record, for each MMU page, that it is no longer in use by the process. This takes place no matter how the process exits, whether of its own violition (by calling a system call) or not (killed by a signal). Pages that are no longer used by any process are marked as reusable.

It's generally good hygiene to free the dynamically allocated storage that you're no longer using, because you never know when a piece of code might be reused in a long-running program. But when a process dies, the operating system will release all of its resources: memory, open file, etc.

The only resources that the operating system won't clean up automatically are resources that are designed to have a global scope on the operating system, such as temporary files.

2

Whenever a process exits either gracefully or through SIGINT,SIGTERM,SIGKILL etc, the exit system call is invoked. Part of the exit call's job is to reclaim any resources that were being used by the process.
Essentially, whenever the OS sees an exit status (success or not) being returned, two things happen:

  1. SIGCHLD is sent to the parent process to let the parent know the child has died
  2. exit system call is invoked which will clean up the resources used by the process that just died

Even for zombie and orphan processes, the OS assigns a special process to trap the exit code from them, and then invoke exit system call.

However, this does not mean that you can get away with not using free() in your code. If you don't, you will bloat the memory requirements for your software, which can in turn slow down the whole system. Anything that is no longer needed should be freed.

  • 1
    Your first paragraph is more or less correct, though technically on a signal the exit syscall isn't called; but exit and a fatal signal trigger a common piece of code in the kernel. After that your answer gets quite a bit wrong: SIGCHLD is called from that common piece of code, not “when the OS sees an exit status” (the exit status is itself also generated by that common piece of code). Zombie processes are already dead, if you see a zombie then the exit processing has already been performed. “the OS assigns … and then invoke exit” is the other way round. – Gilles Apr 9 '16 at 2:00
-2

If certain bits of memory need to be zeroed (e.g. a password or private key), then you'll need a signal handler that calls memset(3) or whatever prior to the process showing itself out the door. See also libsodium, which has some handy and portable routines relevant to this: sodium_mlock, sodium_memzero, etc. Always zeroing all memory after every process exits could be done by the kernel, though would doubtless slow the system down.

Previously used (but possibly unzeroed) memory will be reused by the kernel if necessary; programmers of languages that offer manual memory allocation must be aware that their data structures could contain who knows what from some prior program (the -Wuninitialized compiler flag is relevant here).

And as for StephenKitt's claim that all allocations are always zeroed, well, I guess you could write code on that assumption.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(void)
{
    int i, blahblah[1000000];
    for (i = 0; i < 1000000; i++) {
      if (blahblah[i] != 0) {
          printf("whoops, %d at %d ain't zero\n", blahblah[i], i);
      }
    }
    exit(EXIT_SUCCESS);
}
  • New memory allocations are always zeroed on modern systems, so a new process won't see old values. The point of zeroing memory you no longer need is to avoid values being read from a memory dump while the sensitive application is still running (or perhaps straight from the memory chips before the physical locations have been reused...). – Stephen Kitt Apr 8 '16 at 18:09
  • @StephenKitt I guess you could code on that assumption. Do you? – thrig Apr 9 '16 at 5:43
  • I assume I never get memory containing values from another process, unless arranged specifically (shared memory etc.). If I specifically need zeroed-out memory then I use either calloc() or memset(), since malloc() doesn't clear memory (and it can return memory previously used in the current process – as can also happen with stack-based allocations, as your example illustrates). – Stephen Kitt Apr 10 '16 at 21:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.