Memory management

This is a discussion on Memory management within the C++ Programming forums, part of the General Programming Boards category; I come from a Java/C# world where I don't worry about memory management. In C++, how do you "clean up" ...

  1. #1
    Registered User CompiledMonkey's Avatar
    Join Date
    Feb 2002
    Location
    Richmond, VA
    Posts
    438

    Memory management

    I come from a Java/C# world where I don't worry about memory management. In C++, how do you "clean up" so to speak? I hear of memory leaks from C++ apps all the time, I assume poor memory management is the cause?

  2. #2
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    Anything you allocate with 'new' must be freed once and only once with 'delete'. Anything created with 'new[]' must be destroyed exactly once with 'delete[]'. Whenever you delete a pointer to a base class that actually points to a derived class, and you don't have a virtual destructor, you will have a memory leak.

    So in short, it is poor memory management, though good management can sometimes be very hard to achieve. Prefer container like std::auto_ptr or the Boost ( www.boost.org ) smart pointers to raw pointers to help avoid these problems.
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

  3. #3
    Registered User CompiledMonkey's Avatar
    Join Date
    Feb 2002
    Location
    Richmond, VA
    Posts
    438
    So basically include a virtual destructor for all of my classes? Is there anything similar to a destructor for arrays and anything else I may need to use new for?

  4. #4
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    There are cases when a virtual destructor is unnecessary, or undesirable, but in general, if you are going to inherit from something, it is probably a good idea to have a virtual destructor. For arrays, use 'delete[]'. For example:

    Code:
    int* a = new int[10];
    int* b = new int[10];
    delete[] a; // Good
    delete b; // Very bad... Only frees the memory for the first element.
    Though, in general, it is wise to prefer std::vector or something similar over arrays.
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

  5. #5
    Registered User
    Join Date
    May 2003
    Posts
    161
    Whenever you delete a pointer to a base class that actually points to a derived class, and you don't have a virtual destructor, you will have a memory leak.
    Only if your derived class has member data. Adding new functionality (member functions) through inheritance will not cause memory leaks if it is deleted through a base class pointer.


    So basically include a virtual destructor for all of my classes?
    No. Making any of your functions virtual in any class along an inheritance chain will add 4 bytes (for a vtable) in every instance of every class that inherits that function. Only use virtual destructors if necessary (and in good practice, they will hardly ever be necessary).


    Aside from my beef with virtuals, I agree with everything that Zach said. Prefer pointer wrappers and standard containers to bare pointers and C arrays. (btw, C++ generic containers are MUCH better than Java generic containers)

  6. #6
    Registered User jlou's Avatar
    Join Date
    Jul 2003
    Posts
    1,088
    Originally posted by Zach L.
    Whenever you delete a pointer to a base class that actually points to a derived class, and you don't have a virtual destructor, you will have a memory leak.

    Originally posted by thefroggy
    Only if your derived class has member data. Adding new functionality (member functions) through inheritance will not cause memory leaks if it is deleted through a base class pointer.
    Actually, I believe that whenever you delete a pointer to a base class that actually points to a derived class, and you don't have a virtual destructor, the behavior is undefined. That includes a situation where the derived class has no data members. I base this on a quote from the standard that I read on another website (I don't have a copy of the standard, so this is really hearsay, but here it is):
    In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operandís dynamic type and the static type shall have a virtual destructor or the behavior is undefined.
    So in general I wouldn't ever delete a base class pointer to a derived object without a virtual destructor in the base class. Of course, I wouldn't advise deriving from a base class without a virtual destructor in the first place, but that's a discussion for a different thread.

    -----

    As far as avoiding memory leaks, I'd also advise creating things on the stack unless you have some reason not to. If you create it on the stack, then you can't forget to delete it. If you have to create an object on the heap, then using smart pointers is definitely a good idea.

    I would guess that most memory leaks have nothing to do with virtual destructors. I see them more often when a class has a pointer member variable (using a raw pointer instead of a smart pointer). Or when you have a container of pointers pointing to memory allocated with new. You just have to be vigilant about paying attention to where you allocate memory (with new or new[]) and identifying every place that the object will no longer be needed and can safely be deleted.

    For example, if you have member data allocated on the heap, then you should implement a destructor, as well as a copy constructor and operator= (or optionally make the copy constructor and operator= private so they can't be called). Doing this properly will help avoid memory leaks and crashes and other bad memory things.

  7. #7
    Registered User
    Join Date
    May 2003
    Posts
    161
    whenever you delete a pointer to a base class that actually points to a derived class, and you don't have a virtual destructor, the behavior is undefined.
    Though I would have assumed that slicing will only occur when the derived class has member data, I can't argue with the standard if it labels the behavior undefined. I'll have to fish out my copy and take a look.

    So in general I wouldn't ever delete a base class pointer to a derived object without a virtual destructor in the base class
    Agreed. Though, in the case I mentioned (adding functionality), it wouldn't ever make sense to use a base class pointer anyway.

    Of course, I wouldn't advise deriving from a base class without a virtual destructor in the first place
    Does this mean that you find inheritance useful only for polymorphism?

  8. #8
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    I think slicing is a rather uncommon manifestation of the undefined behavior, given the way new and delete are implemented.
    Same goes for delete with new[], again freeing only the first element is rather improbable.

    But discussion is void for both as there's no reason to have either.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  9. #9
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    Originally posted by thefroggy
    Only if your derived class has member data. Adding new functionality (member functions) through inheritance will not cause memory leaks if it is deleted through a base class pointer.
    That is primarily what I was getting at (though for some reason, not saying).

    On second thought though, I imagine that it probably is undefined according to the standard. At any rate, it is unwise to delete a pointer to a base class that (possibly) points to a derived class is there is no virtual destructor in the base class. Similarly, be careful to use 'delete[]' where appropriate.
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

  10. #10
    Registered User jlou's Avatar
    Join Date
    Jul 2003
    Posts
    1,088
    Originally posted by thefroggy
    Does this mean that you find inheritance useful only for polymorphism?
    Not necessarily. But in many cases it would make just as much sense, if not more, to make global functions that do whatever you are trying to do rather than derive for the sake of adding functionality. In other cases, deriving the class is easier and it doesn't make sense to create global functions, but in those cases I would make sure the base class destructor was virtual just in case. If the extra 4 bytes is important, then I'd go the route of the global function or containment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. tools for finding memory leaks
    By stanlvw in forum C++ Programming
    Replies: 4
    Last Post: 04-03-2009, 11:41 AM
  2. Replies: 7
    Last Post: 02-06-2009, 11:27 AM
  3. Valgrind says I suck at memory management :)
    By carrotcake1029 in forum C Programming
    Replies: 6
    Last Post: 02-01-2009, 07:10 PM
  4. pointers
    By InvariantLoop in forum C Programming
    Replies: 13
    Last Post: 02-04-2005, 08:32 AM
  5. Managing shared memory lookups
    By clancyPC in forum Linux Programming
    Replies: 0
    Last Post: 10-08-2003, 04:44 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21