8

When using dynamically allocated objects in C++ eg:

TGraph* A = new TGraph(...);

One should always delete these because otherwise the objects might still be in memory when control is handed back to the parent scope. While I can see why this is true for subscopes and subroutines of a program, does the same count for the main scope?

Am I obliged to delete objects that were dynamically built inside main()? The reason why this seems a bit redudant to me is that when main ends, the program also ends, so there is no need to worry about memory leaks.

romeovs
  • 5,785
  • 9
  • 43
  • 74

7 Answers7

13

Most of the modern OS always reclaim back all memory they allocated to a program(process).
The OS doesn't really understand if your program leaked memory it merely takes back what it allocatted.

But there are bigger issues at hand than just the memory loss:

Note that if the destructor of the object whos delete needs to be called performs some non-trivial operation and your program depends on the side effects produced by it then your program falls prey to Undefined Behavior[Ref 1]. Once that happens all bets are off and your program may show any beahvior.

Also, An OS usually reclaims the allocated memory but not the other resources, So you might leak those resources indirectly. This may include operations dealing with file descriptors or state of the program itself etc.

Hence, it is a good practice to always deallocate all your allocations by calling delete or delete [] before exiting your program.


[Ref 1]C++03 Standard 3.8 Para 4:

"....if there is no explicit call to the destructor or if a delete-expression (5.3.5) is not used to release the storage, the destructor shall not be implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior."

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • so if I don't explicitly need destructors to be called, and I'm ignoring good practice, I may leave it at that and not delete. – romeovs Apr 23 '12 at 10:40
  • @romeovs: Yes. Memory will be reclaimed by all of the modern OS. – Alok Save Apr 23 '12 at 10:42
  • 3
    @romeovs: Note that just because you *can* do something doesn't mean you *should*. It's still bad form to not delete things. Though one wonders why you're heap-allocating it at all if it doesn't survive the end of the scope. – Nicol Bolas Apr 23 '12 at 10:51
  • The real issue is why he's allocating dynamically to begin with. Maybe because he needs the lifetime to extend beyond the scope of the object? One possible reason for using dynamic allocation in `main` is so that the object can be accessed in destructors of static objects; in that case, he'd better not delete it in main. – James Kanze Apr 23 '12 at 11:09
  • Be careful when referring to _memory_ as you specifically mean memory allocated via `new` or `malloc` here. Your term _resources_ can also include _memory_ reources which are not automatically freed (like shared memory). – edA-qa mort-ora-y Apr 23 '12 at 11:17
7

IMO it is best to always call delete properly:

  • to make it an automatic habit, making it less likely to forget it when it is really needed
  • to cover cases when non-memory resources (sockets, file handles, ...) need to be freed - these aren't automatically freed by the OS
  • to cater for future refactoring when the code in question might be moved out of main scope
Péter Török
  • 114,404
  • 31
  • 268
  • 329
3

Yes, you should call delete, at least because it's best practice. If you have important logic in your destructor, that's one extra reason that you should call delete.

Corrected: If the program depends on logic in the destructor, not calling delete explicitly results in undefined behavior.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • I imagine it was done by one of the other authors of answers. That way their answer is more likely to be bumped up to the top of the list (I've seen it happen to myself before). – Mark Ingram Apr 23 '12 at 09:28
  • -1 Because C++03 3.8 says *"... if there is no explicit call to the destructor or if a delete-expression (5.3.5) is not used to release the storage, the destructor shall not be implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior."* Given that *"You're not required to.."* is **Incorrect**. – Alok Save Apr 23 '12 at 09:51
  • If the *destructor* not *constructor*. – Alok Save Apr 23 '12 at 10:14
  • @Als yes, that's what I said... :D – Luchian Grigore Apr 23 '12 at 10:57
0

The reason why this seems a bit redudant to me is that when main ends, the program also ends, so there is no need to worry about memory leaks.

You're right, but consider this: you create a class object which opens a connection to remote DB. After your program will complete, you should tell the DB "I'm done, i'm going to disconnect", but it won't happen in the case you won't call delete properly.

fogbit
  • 1,961
  • 6
  • 27
  • 41
0

Its the best practice to de-allocate memory that's been allocated. You should keep in mind that Heap memory is limited and just allocating with out de-allocating while your program is running might run the heap space out for some other/or the same program(if its some kind of a daemon that is meant to run for a very long time) that needs heap.

Of course memory will be reclaimed by the operating system at the end of the program's execution.

omggs
  • 1,163
  • 1
  • 11
  • 23
0

I see you are using ROOT (CMS guy?). I think ROOT takes care of this and cleans up, doesn't it?

elelias
  • 4,552
  • 5
  • 30
  • 45
  • I need it for school actually. Besides good suport for high energy physics it is also a pretty nice data-analysis package. Have no clue if RooT cleans up after itself. – romeovs Apr 23 '12 at 10:38
  • @romeovs: a well-designed ([RAII](https://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization)-style) C++ object cleans up after itself *if you make sure the destructor is called*. – Fred Foo Apr 23 '12 at 11:59
  • @larsmans: so without the `delete`, the destrucotr is not called and nothing is cleaned up. – romeovs Apr 23 '12 at 13:25
0

Best practices:

  1. Do not use new, use automatic allocation
  2. When dynamic allocation is necessary, use RAII to ensure automatic cleanup

You should never have to write delete in applicative code.

Here, why are you calling new for TGraph ?

TGraph A(...);

works better: less worries!

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722