45

I just wrote a code in C++ which does some string manipulation, but when I ran valgrind over, it shows some possible memory leaks. Debugging the code to granular level I wrote a simple C++ program looking like:

#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
        std::string myname("Is there any leaks");
        exit(0);
}

and running valgrind over it I got:

==20943== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 26 from 1)
==20943== malloc/free: in use at exit: 360,645 bytes in 12,854 blocks.
==20943== malloc/free: 65,451 allocs, 52,597 frees, 2,186,968 bytes allocated.
==20943== For counts of detected errors, rerun with: -v
==20943== searching for pointers to 12,854 not-freed blocks.
==20943== checked 424,628 bytes.
==20943== 
==20943== LEAK SUMMARY:
==20943==    definitely lost: 0 bytes in 0 blocks.
==20943==      possibly lost: 917 bytes in 6 blocks.
==20943==    still reachable: 359,728 bytes in 12,848 blocks.
==20943==         suppressed: 0 bytes in 0 blocks.
==20943== Reachable blocks (those to which a pointer was found) are not shown.
==20943== To see them, rerun with: --show-reachable=yes

Then it struck me that we have forcefully exited (which i performed in my original C++ code as well). Now the problem is that I want to exit from the program as my previous old code waits for the exit status of the new code. For e.g binary a.out waits for the exit status of b.out. Is there any way to avoid the memory leaks, or should i really worry about the memory leaks as the program is already exiting at that point.

This also raise another question for me, is such a code harmful?

#include<stdio.h>
#include<cstdlib>
int main()
{
        char *p=(char *)malloc(sizeof(char)*1000);
        exit(0);
}
Global Warrior
  • 5,050
  • 9
  • 45
  • 75
  • 56
    returning a value from main() will use that value as the exit code of your process. – tinman Jan 27 '12 at 13:43
  • 2
    Note that, as valgrind points out correctly, you don't have any leaked resources in this case. There's just a few bytes of allocated memory which are still reachable (to which you still have a pointer) at the end of the process life time, but this is not a "leak". – Frerich Raabe Jan 27 '12 at 14:30
  • 10
    As you no doubt have read by now, "return exitcode;" is much better than "exit(exitcode);" because, functionality they both set the exit code status. "return" does a much better job of cleanup, whereas, "exit" is likely to circumvent cleanup. – Stephen Quan Jan 27 '12 at 14:37
  • Have you tried other tools except valgrind? For example deleaker... – MastAvalons Jan 27 '12 at 20:52
  • Note that, when you return a value from `main()`, it's not really an `int`. It is converted to the valid range of exit codes, which is `[0,256)` (at least for Posix). – moooeeeep Feb 02 '12 at 19:15
  • You can use this tool for finding memory leaks:http://theunixshell.blogspot.com/2013/11/finding-memory-leaks-on-solaris-is-no.html – Vijay Nov 29 '13 at 09:08

10 Answers10

65

Use return 0; instead of exit(0); at the end of main. The use of exit circumvents the execution of the destructors.

swegi
  • 4,046
  • 1
  • 26
  • 45
  • As i mentioned i have to use exit because there is another program which is waiting for the exit status of this code. As program a.out is forking to run b.out something like calling C++ code when ur entire project is in C. – Global Warrior Jan 27 '12 at 13:35
  • 38
    Using return 12 for example should return the same exit status to the operating system as exit(12) except it exits cleanly. – jcoder Jan 27 '12 at 13:47
  • 10
    Just to clarify this, @Piyush - *no, you don't need to call exit*. As JohnB says, the integer returned from main is used as the exit status - that's what it's there for. – Useless Jan 27 '12 at 16:19
63

If you insist on using exit():

#include<iostream>
int main(){
    {
        std::string myname("Are there any leaks?");
    }
    exit(0);
}

Also, when you return from main the returned value becomes the application’s exit code. So if you want to pass an exit code, use return exitCode; in main() instead of exit.

Regarding that part:

This also raise another question for me, is such a code harmful?

Yes, because it is a BAD programming habit.

The OS will clean up any memory you failed to release, so as long as you haven't managed to eat all system memory and the page file, you shouldn't damage the OS.

However, writing sloppy/leaky code might turn into habit, so relying on the OS for cleaning up your mess is a bad idea.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
SigTerm
  • 26,089
  • 6
  • 66
  • 115
  • 14
    The OS **might** clean up the memory, it's not really guaranteed to do so (although most usually it will). – TC1 Jan 27 '12 at 14:49
  • 4
    Only a bad OS will not do that. Code is generally bad, unless proven otherwise. – Catherine Jan 27 '12 at 15:39
  • 72
    Pro-Tip: Assume you are running on the Death Station 9000, a machine whose primary operating system allocates memory from the brains of kittens, and only puts it back if told to do so explicitly. Also, any instance of undefined behaviour will result in the destruction of the Earth. – Kaz Dragon Jan 27 '12 at 15:47
  • 2
    The memory is allocated in the process' virtual memory space, and an OS typically has no visibility of allocations made within this space (to my knowledge). When a process exits, its virtual space is then released back to the system; only a severely broken OS wouldn't do this. – boycy Feb 01 '12 at 23:08
  • 2
    @KazDragon Can you motivate this somehow? Cleaning up memory just before the OS is about to do it much more efficiently is plain stupid. You're wasting time, potentially getting all your recently-unused memory back from swap just to release it, increasing your shutdown time by a hundred fold. I shudder at the thought of an OS so bad that it fails to clean up the memory of a dead process, and if you find one, then _that_ is what needs fixing, not your program. – Roman Starkov Feb 03 '12 at 10:12
  • @romkyns: Pro-tip: Remember Murphy's law and assume that failure to clean up resources will get you fired and permanently banned from ever getting another job in programming industry. Much more motivating than "kitten brains". Relying on OS cleanup it is a bad habit, as a result of that habit one day you'll start forgetting to clean up other resources that should have been released earlier. So your software will start leaking gigabytes of memory, abusing system swap and causing system-wide slowdowns. You'll save 3 lines of code by not freeing things yourself. It is not worth the consequences. – SigTerm Feb 03 '12 at 12:23
  • 5
    @SigTerm It's not about saving 3 lines of code. I appreciate how your advice applies to beginner programmers, but there comes a stage when you can do better than that. Why does Firefox take 30 seconds to shut down? Because it's anal about cleaning up stuff that the OS could discard in milliseconds, and because current programming languages do not distinguish between optional resource deallocations and mandatory finalization such as flushing buffers. You propose we give up and just clean up everything. I propose we try a bit harder wherever we can. – Roman Starkov Feb 03 '12 at 12:42
  • 2
    @SigTerm: I completely disagree with you. I also found the “pro-tip” introduction unnecessarily arrogant and condescending. This is not a pro-tip, this is a tip for people who are insecure of their own fallibility. You are not in the position to speak with authority about this, and at least in this case, you are wrong. – Timwi Feb 03 '12 at 12:51
  • 1
    @romkyns: "Why does Firefox take 30 seconds to shut down?" Because it is poorly coded/designed. "you can do better than that" You can't do better than that. You assume that OS is bug free. It is not. If want fast cleanup, profile your code, and IF resource cleanup REALLY is the main bottleneck, implement custom memory/resource manager that will accelerate resource cleanup while allowing you to keep coding defensively. No matter how experienced, human programmer cannot work without producing bugs. Your idea of "making OS clean your mess" doesn't take that human trait into account. – SigTerm Feb 03 '12 at 12:52
  • @Timwi: "I completely disagree with you." I don't really care. My approach work well for me, unless you can offer something that works better, your opinion is not useful for me. "you are wrong" - not a real argument. "insecure of their own fallibility" as far as I know, murphy's law is perfectly secure with human fallability. All people make mistakes. If you think you're an exception from the rule, then you make more mistakes than other people. Making mistakes allow you to learn new things, so you really should enjoy this ability. – SigTerm Feb 03 '12 at 12:56
  • "OS bug" is the worst reason to religiously free memory before exit. Also, check out this quote: "it would be a needless, potentially expensive, and error-prone exercise for the program to explicitly free all of it [just before exiting]" ([source](http://c-faq.com/malloc/freeb4exit.html)) – Roman Starkov Feb 03 '12 at 13:27
  • @romkyns: You might want to reread part about profiling and resource manager. Anyway... I'm not interesting in convincing you or arguing with you - it'll take too much time, and I'll gain nothing from doing that. It is your code, your life, and your consequences to deal with so do whatever you want - I don't care, because it is not my problem. If you want to argue, you'll have to find somebody else. Have a nice day. – SigTerm Feb 03 '12 at 13:39
  • @romkyns It was supposed to be a funny, with a nod back to the USENet days (where the DS9K was regularly outed, nasal demons and all.) But there is a serious side - for example, a runtime analysis program may not be able to tell the difference between your deliberate leaks and *real* leaks. So that behaviour may well hide real errors that need fixing. And that, for me, counts as bad practice. – Kaz Dragon Feb 03 '12 at 17:00
  • 3
    @SigTerm: For someone who doesn’t want to argue, you seem to be doing a lot of arguing :) – Timwi Feb 05 '12 at 21:09
22

This also raise another question for me, is such a code harmful?

#include<stdio.h>
int main()
{
        char *p=(char *)malloc(sizeof(char)*1000);
        exit(0);
}

It's not harmful on modern operating systems, because they will close all resources owned by a process automatically when the process ends.

However, it's still bad practice, and might lead to subtle and hard to find errors when, over several years of maintenance, the code slowly changes until, on day, this does become harmful. I have worked in projects where some of the code was a decade old and I have learned a few lessons doing so, some of them rather harsh. Therefore, I would avoid writing such code, even if it currently doesn't pose a problem.

sbi
  • 219,715
  • 46
  • 258
  • 445
  • 27
    But it can be harmful to maintainers of your code, who will have a harder time using tools like valgrind to track down legitimate problems. – John Zwinck Jan 27 '12 at 13:30
  • @JohnZwinck Perhaps that's an argument for why such tools should be improved. I mean they are currently preventing a legitimate technique: not spending time to do something that the OS can do far better. – Roman Starkov Feb 03 '12 at 12:43
  • If you want, write a "fastTeardownWithoutMemoryDeallocation()" function in your C or C++ program. When and if it is called, then "forget" all your free() and delete calls and terminate. But writing classes which do not clean up in their destructors is bad, because you don't know which classes are used temporarily at runtime and which are "permanent" until program shutdown. – John Zwinck Feb 04 '12 at 01:09
5

In most cases, it's worth cleaning up after yourself, for the many good reasons already given: better maintainability, better utility from checking tools and so on.

If there are other functional reasons to clean up, maybe your data is saved to a persistent store, then you have no choice - you must clean up (although you might want to reconsider your design).

In some cases however, it may be better to just exit and "leak".

At the end of a program, your process is going to exit. When it does so, the operating system will recover any memory allocated by your program and in some cases it can do this much more quickly.

Consider a large linked list, where each node is dynamically allocated, and carries a substantial dynamically allocated structure. To clean this up you must visit each node and release each payload (which in turn may cause other complex structures to be walked).

You may end up performing millions of memory operations to run through such a structure.

The user wants to exit your program, and they sit there for 10s of seconds waiting for a bunch of junk processing to happen. They cannot possibly be interested in the result - they're quitting the program after all.

If you let this "leak", the operating system can reclaim the entire block of memory allocated to your process much more quickly. It doesn't care about the structures and any object cleanup.

http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx

Ultimately you must understand what your tools are telling you, to be sure you're using them properly.

Rob
  • 4,210
  • 3
  • 30
  • 25
  • 1
    +1 for the most nuanced answer to this question. Writing code expressly to clean up dynamically-allocated memory at program termination is as silly as enclosing function bodies in an extra pair of `{}` to "make sure" automatic variables are destroyed when the function returns. – user168715 Feb 06 '12 at 21:15
4

To avoid the memory leak, return the status from main instead of calling exit. If you're returning zero, you can omit the return statement if you like; the program will exit with a status of zero in that case.

This also raise another question for me, is such a code harmful?

On a modern operating system, it won't cause any harm - all resources are reclaimed automatically when a program terminates. However, it does make it harder to use tools like Valgrind to find genuine problems, so it's best to avoid even harmless memory leaks if you can.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
2
#include<iostream>
using namespace std;
int main()
{
    {
        std::string myname("Is there any leaks");
    }
    exit(0);
}
Peter Wood
  • 23,859
  • 5
  • 60
  • 99
1

At the time your process is actually exiting, as when main() exits, the OS will reclaim all resources allocated to your application either way. How you exit isn't so important - at least with regard to dynamic memory.

If you have some distributed database connection open or something, you should use atexit() handlers to close it, and forceful termination with straight-up exit may make them not run which would be bad - but as far as your OS resources are concerned you're probably okay.

You should also always make sure you release (manual) file locks and similar things as they may not go away due to a process exit.

John Humphreys
  • 37,047
  • 37
  • 155
  • 255
1

If you'd like to break an execution and pass a return code without surpassing destructors, throw an exception, and extract the return value from the exception in main().

Rafał Rawicki
  • 22,324
  • 5
  • 59
  • 79
  • Why would you want to do this rather than calling `std::exit()`, though? And what about that maintenance programmer, who'll put in a `catch(...)` three years from now, because he didn't think that anything else but his 13 exception types (which he's to lazy to organize) can come out of that one submodule? – sbi Jan 27 '12 at 22:21
0

If the program is exiting, you do not have to worry about memory which was allocated with malloc or new. The OS will take care of it - anything in your process' virtual address space exclusively will go away when the process dies. If you're using shared memory or named pipes it could still be a concern.

Borealid
  • 95,191
  • 9
  • 106
  • 122
  • 3
    Still, it must be kept in mind that `exit` doesn't call destructors for objects allocated on the stack (so e.g. file buffers may not be flushed), so you should probably avoid it anyway. – Matteo Italia Jan 27 '12 at 13:33
0

To add a different opinion.

Such code is not harmful hat all. The OS will care for everything when the process terminates. Everything else results in an unstable OS. Just ensure that your persistent data (files, ...) is consistent.

To go a bit further and provocatively states, explicitly freeing memory on program exit can be harmful.

  1. Program exit takes longer (Did you ever get annoyed to wait for a program to exit until the computer shuts down?)
  2. The correct order of destruction is not always trivial, especially with 3rd party components (I remember some programs that likely crash on exit)
  3. The OS may not let you free memory after leaving main(*) and kill your program instead

Do you risk this just to make Valgrind give you a specific output?(**)


(*)

#include<iostream>
using namespace std;
std::string myname("Is there any leaks");
int main() {
        exit(0);
}

(**) Well, of course the output of any memory analyzer is more useful without "noise". What about only freeing memory explicitly on exit in debug mode?

Meinersbur
  • 7,881
  • 1
  • 27
  • 29