3

I have searched the internet for hours and hours and came up with these steps to prevent memory leaks (w/o use of smart pointers and advance tools as such). Please let me know if there are any issues with any of the below findings... Thanks in advance.

  1. for each new there should be a delete.
  2. if the new is inside a class putting the delete in the destructor would take care of the dynamically allocated memory.
  3. if you do a new object obj from class foo in main then in you would have to explicitly delete obj.
  4. if you have multi-dimentional dynamic arrays you have to delete both levels. (I am a bit unsure of this being safe... I thought just one delete for the ptr might do it but after thinking harder I figured it is a dynamic array of dynamic arrays and should treat each as a dynamic array separately).

ex 1.

char *ptr;
ptr = new char[size];
// Some Code here
delete ptr;

ex 2.

//foo.h
class foo { 
private:
    char * ptr;
public
    foo();
    ~foo();
};
// foo.cpp
foo::foo()
{
    ptr = new char[100];
    for (int i = 0; i < 100; i++)
        ptr[i] = i;
}

foo::~foo()
{
    delete ptr;
}

ex 3.

//main.cpp   foo class stays the same as ex 2.
int main()
{
    foo obj = new foo();
    // Some code here
    delete obj;
    return 0;
}

ex 4.

//foo.h
class foo {
private:
    char ** ptr;
public
    foo();
    ~foo();
};

//foo.cpp
foo::foo()
{
    ptr = new char[100];
    for (int i = 0; i < 100; i++)
        ptr[i] = new char[100];
    for (int i = 0; i < 100; i++)
        for (int j = 0; j < 100; j++)
            ptr[i][j] = i;
}

foo::~foo()
{
    for (int i = 0; i < 100; i++)
        delete ptr[i];
    delete ptr;
}
Ali Zand
  • 41
  • 2
  • 1
    In ex1, you must call `delete[] ptr` since it is an array of `char`, look here: http://www.cplusplus.com/reference/new/operator%20delete%5B%5D/ Same issue on ex2, add `[]` in the destructor. Ex3 is ok. For Ex4 add the same `[]` for both the `delete` in the destructor. Hope it helps! – gmas80 Oct 30 '14 at 03:25
  • 2
    This question appears to be off-topic, there is no real question here, you just want us to review your examples. Therefor you should post this on http://codereview.stackexchange.com instead. – Scott Chamberlain Oct 30 '14 at 03:27
  • Aren't 2, 3 and 4 just applications of 1? 1 should be enough, though it should have a corollary: "Don't use `new`." – Kerrek SB Oct 30 '14 at 03:28
  • I guess my question was any of these correct... Thank you so much @gmas80 That was very helpful. – Ali Zand Oct 30 '14 at 03:30
  • 1
    **5.** If you use `[]` when you `new` you *must* use []` when you `delete`. **ex. 5** `o = new Object; delete o;` vs `array = new char[100]`; delete[] array;`. – Galik Oct 30 '14 at 03:32
  • Have you actually tried these? For one, your ex:2 and ex:3 won't compile. (You should be getting errors about the compiler's inability to automatically convert an `int` to a `char`, or a `foo` to a `foo *`.) Ex:4 should have the same issue (`new char[100]` is a `char*`, not a `char**`.) – cHao Oct 30 '14 at 03:33
  • 3
    Smart pointers and vectors and such are so much less hassle than manually managing your memory. I wouldn't call that advanced. Vectors can be used just like arrays for the most part and smart pointers can be used just like pointers for the most part. – chris Oct 30 '14 at 03:37
  • 1
    There is one glaring omission from your strategy: deep copies. For example, in your ex 2 and 4, you need to implement deep copy (and move too), otherwise, accidentals copies of your objects will cause double deleting of the memory (which usually causes a corruption of the heap, which is really bad!). See [the Big Five](https://www.daniweb.com/software-development/cpp/tutorials/373787/beginning-c0x-making-a-raii-class). – Mikael Persson Oct 30 '14 at 05:09

2 Answers2

4

Below are some tips you need to take care while managing memory on your own:-

First and most important of all is:-

1) Always use delete with new and delete[] with new[].Mixing these would result in undefined behavior.

2) Never combine malloc/delete OR new/free.

For your question "if you have multi-dimentional dynamic arrays you have to delete both levels." Yes you have to take care of them.

Things you mentioned are correct i.e you have to explicitly delete the memory whenever you are allocating memory in heap. Though you missed one important aspect which revolves around RAII. Let's say there's a function in which you are taking care of allocation/deallocation.

void fun ()
{
 1) int* ptr;
 2) ptr = new int;   //allocated memory.

 3) ...              //do something with ptr.

 4) delete ptr;     //done with ptr now delete it.
}

Now you are doing good by deleting memory which you allocated using new. However, there could be a chance that program execution won't even reach to your delete. ( in case exception is thrown in STEP#3). That case would constitute a memory leak.

To care of these issues we have smart pointers based on the concept of RAII. They will automatically delete the memory they are referring to whenever go out of scope that means you don't need to take care of memory management.

ravi
  • 10,994
  • 1
  • 18
  • 36
  • 1
    Don't make the mistake of thinking smart pointers will solve all problems. :) You do have a bit to take care of; it's just more design work and less bean counting. (You need to pick the right type of smart pointer, for example. And you have to use them correctly.) – cHao Oct 30 '14 at 03:42
  • I think you meant to say RAII, not RTTI. This has nothing to do with RTTI (Run-time Type Identification), but it has everything to do with RAII (Resource Acquisition Is Initialization). – Mikael Persson Oct 30 '14 at 05:06
1
  1. for each new there should be a delete.

Yes. And to be more precise: Every new must have a matching delete, and every new[] must have a matching delete[]

  1. if the new is inside a class putting the delete in the destructor would take care of the dynamically allocated memory.

No! You also should take care on what should happen for copies through copy constructor or assignment, unless you explicitly forbid these operations. See What is The Rule of Three? for more details.

  1. if you do a new object obj from class foo in main then in you would have to explicitly delete obj.

?? See 1.?

  1. if you have multi-dimentional dynamic arrays you have to delete both levels. (I am a bit unsure of this being safe... I thought just one delete for the ptr might do it but after thinking harder I figured it is a dynamic array of dynamic arrays and should treat each as a dynamic array separately).

Yes, you always have to take care about proper memory management, if you're using raw pointers, no matter how many levels of indirection.


My final advice is, leave your head clean about bothering with such questions, but use the stuff provided with the <memory> smart pointers, and standard c++ containers.

Don't use new/delete directly, unless you're a 100% sure what you're doing, and you're a 200% sure you really need to do it.


As you're asking about actual issues:

(ex 2.) The delete doesn't match the new char[]

ptr = new char[100];
           // ^^^^^

foo::~foo() {
    delete [] ptr;
        // ^^ put the square brackets there
}

same for (ex 4.)

Community
  • 1
  • 1
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • Great advice. Thank you so much for your help. I guess I forgot to mention that I am learning C++ and it is required for this class project to use them. – Ali Zand Oct 30 '14 at 03:52
  • @AliZand: A good teacher should have showed you the normal methods first (vector, string, smart pointers, etc) before delving into the manual stuff (which is so rare that many programmers never need it) – MSalters Oct 30 '14 at 11:34