0

I've been toying with c++ for a little while, and coming from java one of the most confusing aspects for me is memory management. For example, lets say I have a method, and in that method I declare a pointer to an object, i want to set that pointer to an attribute of another object using a get method:

SubObject *mySubObject = anotherObject.getSubObject();

My question is, what happens to this pointer when the method ends? should i use the following before it ends?

delete mySubObject;

What if i don't delete it? Does it remain until the entire program ends?

I've tried googling around for basic memory management tutorials for c++, but i typically find more advanced stuff thats way over my head, any referals would be appretiated.

kbirk
  • 3,906
  • 7
  • 48
  • 72

9 Answers9

9

Tracking memory management can be a burden, the best advice is to avoid it in as much as possible and make it explicit by avoiding raw pointers. If you only need temporary access to a variable that is held somewhere else (in your example, it is a member of a different object, and thus managed there) you should not delete it, and it will be better if you just hold a reference rather than a pointer, as references make explicit the fact that you are not managing that resource.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • can you please ellaborate on this `reference`? Or just link me? I'm a C programmer starting my migration to C++ and that seems like a very good way to document code – Vinicius Kamakura Jun 19 '11 at 22:31
  • 1
    Basically you need to read the docs for the given function. Unfortunately, a lot of docs for C++ libraries don't mention if you own the returned pointer or not. – André Caron Jun 19 '11 at 22:31
  • 1
    @hexa: you should get some good introductory book or tutorial. References are a feature of C++ to create an alias for an existing object. Under the hood, they can be implemented as automatically dereferenced pointers, but the important point is that they are guaranteed not to be null, and they don't *hold* a resource (memory). As a simple motivating example: `int main() { int i = 0; int & r = i; r = 5; std::cout << i; }` will print 5. The variable `r` is an alias to `i` (variable from which it was initialized) – David Rodríguez - dribeas Jun 19 '11 at 22:36
  • oh i see. I've seen that in inumerous calls, methods i've been working with in Qt and always thought they were just pointers. I really need to get down to a book and read it through instead of picking up stuff along the way in the not so optimal way :P thanks – Vinicius Kamakura Jun 19 '11 at 22:39
3

If that getSubObject() method simply returns a pointer to a previously allocated mySubObject, you should not delete it, because that should be the responsibility of the class that allocated it in the first place. Also that pointer might not even have been allocated through a new and be in the stack, so deleting it could potentially lead to bigger problems.

As a rule of thumb, delete what you have new'd. Of course that heavily depends on the layout of the programming.

Vinicius Kamakura
  • 7,665
  • 1
  • 29
  • 43
3

To answer the question in your post title, you should use delete[] if and only if you allocated memory with new[]. You should use delete if and only if your used new to allocate memory.

int *array = new int[10];
int *ptr = new int;
...
delete[] array;
delete ptr;

To answer your post, you should ask yourself when your code allocates memory. In fact, you should think of memory as a resource, like a file handle or network connection. Anytime you open a file in C++ or Java, after you are done, you should close the files. Likewise, anytime you allocate memory in C++, you should free it. The tough question is when you should free the memory. So does the method

anotherObject.getSubObject();

return a pointer to a newly allocated object? Whose job is it to free the memory pointed to by the pointer returned in the above method?

If the above method uses new and returns a pointer to that newly allocated memory, then the client (the programmer who called the method) must delete the memory. However, if the pointer returned by the method is freed by the object anotherObject when its destructor is called, then the client should NOT free the memory referenced by the pointer.

If you are new to C++ from Java, you should definitely try using references when possible, and check out smart pointers. The nice thing about smart pointers is that they provide automatic memory management (you don't have to worry about deleting after you have newed an object).

Chris
  • 2,786
  • 1
  • 28
  • 31
  • 1
    +1, smart pointers are almost always the best way to deal with memory management in C++. – Matteo Italia Jun 19 '11 at 22:37
  • 3
    Another best way to deal with dynamic memory allocation, is to not use it unless you have to... believe me it works well! – Armando Jun 19 '11 at 22:49
  • True, smart pointers and the boost pointer containers are a great way to go, but they ain't recommended for programs that have to run FAST. My boss is a person who doesn't mind letting us spend two months debugging our programs with Purify, provided we don't use smart pointers. I tried a few programs myself, and smart pointers were taking up a lot of extra milliseconds in our program which involves a lot of copying, creation & destruction of pointers. – Nav Jun 20 '11 at 04:25
1

To answer the question in the topic: In C++ you use delete [] to delete an array allocated with new[]. Ie:

int *a = new int[10];  // Allocate 10 ints and save ptr in a.
for (int i=0; i<10; i++) {
    a[i] = 0;    // Initialize all elements to zero.
}
delete [] a; // Free memory allocated for the a array.

As Gustavo correctly points out the reason for the [] in the delete invocation is to make sure the destructor gets invoked in each of the elements of the array.

Avada Kedavra
  • 8,523
  • 5
  • 32
  • 48
1

As you just trying to learn basic C++ memory management, forget all the answers about references and smart pointers.

Learn the basics and later you can return to these "advanced" subjects.

Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
0

Without knowing details about getSubObject(), there is no way to know how to truly answer the question. The answer should lie in the documentation for getSubObject() (But not everyone follows that should.) That documentation might be in some old-style document, some doxygen (or similar) page, the header file that declares getSubObject(). If worst comes to worst, you'll need to look at the source code that defines getSubObject(), assuming that the source is available.

When reading that documentation/header/source, you should be looking for an answer to the question "Does getSubObject() allocate memory that the caller must delete, or does it merely return a pointer to an existing object?" With a name like getSubObject() I would expect the latter is the case. I would expect the former if the name of the function was createSubObject().

David Hammen
  • 32,454
  • 9
  • 60
  • 108
0

There is no right answer into that. If the pointer returned by the member function (or method if we are using java lingo) is pointing into an object allocated in the stack, your program will crash if use the keyword delete on it.

Should the caller or the callee be responsible for memory management if you are using the free storage? If another person calls the member function, Now you have a dangling pointer. And what about if the callee is using RAII?

Since you are learning (kudos for that) , try to learn the basics of memory management first. Once you have a basic understanding of memory, you will be more comfortable with C++ and memory management.

If you are doing production code, and you have to do it in C++. The safest way to avoid all these issues is to use dynamic memory allocation only when you need to, until you have a better understanding of it. In my opinion, even when you have a good understanding of dynamic memory allocation, you should have a good reason why you are using it.

Good luck,

Armando.

Armando
  • 688
  • 6
  • 15
0

In C++, you have to manage the memory allocation all on you own, there is no garbage collection of bits you have forgotten to clean up as java/C# and any other modern language has. If you lose track of memory, at best it's leaked, at worst, you continue to use it while something else does. It's a hard problem to solve, very few, if any, C++ programers get this right, so smart pointers and other esoteric advanced magic is performed to get around these issues in C++. @yi_H is correct, get to understand the basics of basic memory allocation, so you know why Smart Pointers are such a good idea.

Without smart pointers, while a few of the answers above have eluded to it, "ownership" is the most critical thing to understand. Whenever you have a pointer to a block of memory, you must know who owns it. If you own it, you must free it before it goes out of scope or it's lost. If you give someone else a copy of it, ensure that you define who owns it, and when the owner can/will/should free it. If you cannot do this, you are hosed. As a rule, C++ libraries are notoriously bad at documenting this, so in the absence of clear information, assume you do not own it (Do not delete it and potentially create a memory leak) in preference to deleting it and creating hard to find defects. Use Valgrind to find memory leaks on the working program.

To avoid the worst pitfalls, obey some simple rules. Use locals and references in preference to heap (new). When returning allocated memory, clearly document the ownership and life cycle of the allocated memory. Avoid making copies of pointers to allocated memory, copy the data where possible. When making copies of pointers, make the scope as small and short life time ass possible. Much use of pointers is done (badly) in the name of efficiency- a program that runs slowly is far more efficient that one that randomly core dumps.

i.e. Limit the use of the keyword "new".

mattnz
  • 517
  • 2
  • 13
0

Well the design shouldn't be like this that you get a pointer from another object and delete it.

SubObject *mySubObject = anotherObject.getSubObject();
delete mySubObject;

If you delete mySubObject in that point anotherObject class functions may still use it. You should follow OOP approaches. The object that is returned by getSubObject() function should be created/allocated memory from constructor and deallocated in a destructor. And yes reference is better here so that mistakenly a delete is not performed outside the class. Thanks.

Atiq Rahman
  • 680
  • 6
  • 24