I am writing a c terminal program that runs until the user terminates it with Ctrl+C. Think something like ping or top.
My program allocates to the heap but starts no other threads or processes. Should I be handling SIGINT and freeing any allocated memory before exit or is leaving it to the OS better practice?
The short answer is yes given your context, which is a normal exit situation. In an abnormal exit situation, then the short answer is absolutely no.
If you are concerned that your program is leaking memory during its execution, which is a bad thing in the sense that it slows your program execution, then you can keep track of the memory that you allocate and then free it before you exit. Then you can run your program with valgrind and if valgrind complains about blocks that weren't free'd, then you will know you have some type of leak. The location of the allocation will help you know if the leak is of any importance.
If you exit anyway, you don't need to release any resources. The OS will take care of it just fine, and there is no benefit in doing it manually.
Note that free() is not async-safe, so you would definitely have to do the actual freeing in the main thread, and not in the handler. But don't do that, unless you want to do other things than exit().
Use SIGINT handlers for things like resetting the terminal (e.g. with ncurses), or saving critical state.
Related
In my program written with C and C++, I will new an object to fulfill the task, then delete the object.
At the moment after new object but before delete object, if the user presses ctrl+c to break the process, that will cause delete not to be called and a memory leak occurs.
What should I do to avoid this situation?
Also, if the memory was reclaimed by the OS, what about the opened files? Are they closed by the OS or should I close them manualy?
In a virtual-memory-based system, all memory is returned to the OS when a process is terminated, regardless of whether it was freed explicitly in the application code. The same might not be true of other resources, however, which you may want to free cleanly. In which case, you need to provide a custom signal handler for the SIGINT signal (which is received on Ctrl+C), see e.g. http://linux.die.net/man/2/sigaction.
Pressing CtrlC will send a SIGINT to the process, which by default does a mostly-orderly shutdown, including tearing down the memory manager and releasing all allocated heap and stack. If you need to perform other tasks then you will need to install a SIGINT handler and perform those tasks yourself.
If you allocated any SYSV Shared Memory Segments using shmget(2) then you must clean up after yourself with shmctl(2).
If you allocated any POSIX Shared Memory Segments using shm_open(3) then you must clean up after yourself with shm_unlink(3).
Both SYSV and POSIX shared memory segments persist past process termination. You can see what persists using the ipcs(1) tool.
Of course, if you haven't used any SYSV or POSIX shared memory segments, then this is all just noise. :)
You are subscribing to a rather common misconception that heap blocks that are not freed, but still accessible at the time a program exists are leaks. This is not true. Leaked blocks are those which no pointer still references, hence they can't be freed.
Through the years of playing with (and breaking) lots of perfectly good kernels, I have never managed to sufficiently break a virtual memory manager to the point where it no longer reclaimed the entire address space of a process once it exited. Unless you are working with a kernel clearly marked as 'new and experimental', you will have better luck winning the lottery than finding a system that doesn't employ an effective virtual memory manager.
Don't put cruft in your code just to get a perfect score in Valgrind. If you have no real clean up tasks to do other than freeing memory that still has valid references, you don't need to bother. If someone throws a kill -9 to your program, you won't be able to handle it and will see the old behavior repeat.
If you have file descriptors to clean up, shared locks to relinquish, streams to flush or whatever else must happen so other processes don't miss you when you're gone, by all means take care of that. Just don't go adding code that does nothing to solve a non-problem, it just seems silly to do so.
Note
This was originally going to be a comment, but is far too long and SO frowns on writing a novel one comment at a time.
When CTRL+C is pressed in a Linux console, the SIGINT signal is sent to the application which, if the signal has no handler, will terminate the program, returning all memory to the OS. This of course would make it pointless to do any freeing of memory, since all memory will freed once the program exists. However, if you would like to handle the CTRL+C SIGINT signal (maybe to write out some last data to a file or do some other cleanup), you can use the function signal() to install a function to be called when the signal is received. Check out the man page for this function if you want to learn more.
If the process quits, a memory leak will NOT normally occur.
Most of the memory you allocate will be freed on Ctrl+C. If you see memory usage not return to its prior level, it is almost certainly caused by buffered filesystem blocks.
However, you should definitely clean things up, in particular if you have used any other types of resources:
Files created in temporary directories won't be deleted. This includes /dev/shm, leaving such a file could be considered a "memory leak".
System V or posix shared memory segments won't get thrown away when your process quits. If this bothers you, clean them up specifically. Alternatively, clean them up on a subsequent run.
Normally a leak (of a persistent or semi-persistent object e.g. file) doesn't matter if a subsequent run doesn't leak more memory. So cleaning up on a future run is good enough.
Imagine a process running every 5 minutes from "cron", if it crashes on each run and leaves some mess, it's still ok provided each run cleans up the mess from the previous crash.
The OS will reclaim the memory allocated by the process when the process exits as a result of Ctrl-C or any other means.
As the title says, would all the pointers be freed after the child dies or do I have to free them manually?
Yes,
The OS is a good housekeeper and tidys up for you.
But being a good guest it is better to do it yourself.
Perhaps files need to be closed, network connections tidied up
When a process dies, the kernel cleans up all the memory which process was using, unless it was shared with some other process. This does not technically involve "freeing the pointers" in the sense of a call to free(), instead the kernel frees up the blocks of memory which the C library had used to implement malloc().
However I like to make sure my programs always free() everything they malloc() (I check using valgrind) because this makes me more confident that the individual parts are not leaking memory. That is especially important in long-running programs, but just seems like the "right thing" even in other programs.
In C, if I allocate a memory using malloc and during the execution, the program encounters an exception/error and exits with a manually incorporated exit(1) statement in the program, does C compiler automatically frees the memory before making the unexpected exit or do I have to manually do this just before the exit(1) line in the program.
I use the gcc-4.5.2 compiler on Ubuntu 32bit platform.
Once you call exit, OS takes all the allocated memory back. So no need to call free.
Edit:
But It's generally good practice to free memory you allocated in your program as you may overlook it the call to free when you modify it in the future.
On a well-designed operating system, when a process exits (either using exit(), die(), abort() or raise() or by being killed by an error, a signal or whatever else), the operating system should free up all the resources used by the process, including stack space, heap, the allocated memory (usually on the heap), close the open file descriptors (if it's a *NIX system) etc.
However, I won't go for 'No need to call free()'. It's a bad programming/design concept if you don't explicitly free() memory that you have malloc()'ed and although you eventually can rely on the OS to do this for you, it may cause memory leaks when you later modify your project not to exit but you forget to free() your used memory.
hello everyone I have some question about threads if for example I have some thread 1 which allocates some piece of the memory, and anohter thread (let's assume 2) is killing thread 1 using pthread_cancel() or just using return what is going on with the peace of memory which it allocated? will be leak if thread 1 didn't free this piece of memory? thanks in advance for any answer
edited
just to make it clearer, as I know pthread_cancel() kills thread, but what is going on with its memory when I kill it? In case of return all thread will be dead if 1 is the main thread
Yes, it will leak memory in that case. C does not have any garbage collection -- if you allocate memory and fail to free it, it will be leaked, plain and simple.
If you want to avoid leaking memory, don't call pthread_cancel. Make your threads exit gracefully by setting a flag asking them to exit, and then when they detect that that flag is set, they can free their memory and kill themselves by returning from their thread procedures or by calling pthread_exit.
Alternatively, you can set a thread cleanup handler by calling pthread_cleanup_push, which will get called when your thread exits or gets canceled by a call to pthread_cancel. You can use a handler function which will free any allocated memory you have outstanding.
First of all whether it gets cancelled immediately or not depends on cancellation state.
please check "pthread_setcancelstate" and "pthread_setcanceltype".
Also it is important to have a handler after a thread is cancelled.In the handler all the resources must be freed, like locks and memory, it is similar with the return.So, Yes, there is a chance of leak if implementation is not right.
I suggest to look at the implementation of a method or function before using it.
Hope this helps.
In my program written with C and C++, I will new an object to fulfill the task, then delete the object.
At the moment after new object but before delete object, if the user presses ctrl+c to break the process, that will cause delete not to be called and a memory leak occurs.
What should I do to avoid this situation?
Also, if the memory was reclaimed by the OS, what about the opened files? Are they closed by the OS or should I close them manualy?
In a virtual-memory-based system, all memory is returned to the OS when a process is terminated, regardless of whether it was freed explicitly in the application code. The same might not be true of other resources, however, which you may want to free cleanly. In which case, you need to provide a custom signal handler for the SIGINT signal (which is received on Ctrl+C), see e.g. http://linux.die.net/man/2/sigaction.
Pressing CtrlC will send a SIGINT to the process, which by default does a mostly-orderly shutdown, including tearing down the memory manager and releasing all allocated heap and stack. If you need to perform other tasks then you will need to install a SIGINT handler and perform those tasks yourself.
If you allocated any SYSV Shared Memory Segments using shmget(2) then you must clean up after yourself with shmctl(2).
If you allocated any POSIX Shared Memory Segments using shm_open(3) then you must clean up after yourself with shm_unlink(3).
Both SYSV and POSIX shared memory segments persist past process termination. You can see what persists using the ipcs(1) tool.
Of course, if you haven't used any SYSV or POSIX shared memory segments, then this is all just noise. :)
You are subscribing to a rather common misconception that heap blocks that are not freed, but still accessible at the time a program exists are leaks. This is not true. Leaked blocks are those which no pointer still references, hence they can't be freed.
Through the years of playing with (and breaking) lots of perfectly good kernels, I have never managed to sufficiently break a virtual memory manager to the point where it no longer reclaimed the entire address space of a process once it exited. Unless you are working with a kernel clearly marked as 'new and experimental', you will have better luck winning the lottery than finding a system that doesn't employ an effective virtual memory manager.
Don't put cruft in your code just to get a perfect score in Valgrind. If you have no real clean up tasks to do other than freeing memory that still has valid references, you don't need to bother. If someone throws a kill -9 to your program, you won't be able to handle it and will see the old behavior repeat.
If you have file descriptors to clean up, shared locks to relinquish, streams to flush or whatever else must happen so other processes don't miss you when you're gone, by all means take care of that. Just don't go adding code that does nothing to solve a non-problem, it just seems silly to do so.
Note
This was originally going to be a comment, but is far too long and SO frowns on writing a novel one comment at a time.
When CTRL+C is pressed in a Linux console, the SIGINT signal is sent to the application which, if the signal has no handler, will terminate the program, returning all memory to the OS. This of course would make it pointless to do any freeing of memory, since all memory will freed once the program exists. However, if you would like to handle the CTRL+C SIGINT signal (maybe to write out some last data to a file or do some other cleanup), you can use the function signal() to install a function to be called when the signal is received. Check out the man page for this function if you want to learn more.
If the process quits, a memory leak will NOT normally occur.
Most of the memory you allocate will be freed on Ctrl+C. If you see memory usage not return to its prior level, it is almost certainly caused by buffered filesystem blocks.
However, you should definitely clean things up, in particular if you have used any other types of resources:
Files created in temporary directories won't be deleted. This includes /dev/shm, leaving such a file could be considered a "memory leak".
System V or posix shared memory segments won't get thrown away when your process quits. If this bothers you, clean them up specifically. Alternatively, clean them up on a subsequent run.
Normally a leak (of a persistent or semi-persistent object e.g. file) doesn't matter if a subsequent run doesn't leak more memory. So cleaning up on a future run is good enough.
Imagine a process running every 5 minutes from "cron", if it crashes on each run and leaves some mess, it's still ok provided each run cleans up the mess from the previous crash.
The OS will reclaim the memory allocated by the process when the process exits as a result of Ctrl-C or any other means.