4

I am new to c++ and I just learned about dynamic memory and memory leaks.

From what I understand, when creating a pointer(int *ptr = new int), and then changing the address that he is pointing, the old address still exist/allocated. (please correct me if I am wronge).

so I thought about this:

int *ptr;
ptr = new int;

first ptr is fill with random(or not?) address, then I change it, so the old one stays? if I try this code:

int *ptr;
cout << ptr << endl ;
ptr = new int;
cout << ptr << endl ;

I get:

0x401a4e
0x6d2d20

Does it mean that 0x401a4e is part of a memory leak? Or is it released when ptr moves to dynamic memory? How does it work?

Bart
  • 19,692
  • 7
  • 68
  • 77
Barry
  • 43
  • 3
  • possible duplicate of [Does using references instead of pointers, resolve memory leaks in C++?](http://stackoverflow.com/questions/6783939/does-using-references-instead-of-pointers-resolve-memory-leaks-in-c) – Jerry Coffin Aug 08 '12 at 19:50
  • It should be pointed out that once you have learned the basics of memory management (see Konrad Rudolph below for a succinct description) then you should stop using it in preference of automated memory management via smart pointers/containers. In real code it is very rare for you to manage RAW pointers manually. – Martin York Aug 08 '12 at 21:02

4 Answers4

15

You need to understand that memory leaks are not about pointers (really: never – even though a lot of people will claim something different). The whole business with pointers is just misleading.

They are about a mismatch in dynamic memory allocations and deallocations.

Every allocation via new must be matched with exactly one deallocation via delete. Same for malloc and free and new[] and delete[] (and other conceivable dynamic resource allocation functions).

int* x; // Not a memory leak: no dynamic allocation
new int; // Memory leak: we acquired a value via `new` and lost it.

int* y = new int;
int* z = y;
delete y; // Not a memory leak any more: we freed the memory.

delete z; // Oooh, bad: we deleted a value twice. The horror.

Modern C++ code uses very few (in most cases: no) manual dynamic memory allocations. That way, you cannot have leaks. In principle. This is very good, so do it. Instead of manual dynamic memory allocations, you can make use of standard containers and smart pointers which handle the memory management for you.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • I always wondered why delete doesn't automatically set the pointer to NULL. At least it'd help people with spaghetti code. –  Aug 08 '12 at 20:04
  • 1
    I would argue that modern c++ code still uses manual dynamic memory allocations (sometimes even a lot of them), but avoids the potential for leaks by immediately stuffing the allocated memory into some sort of smart pointer. – Grizzly Aug 08 '12 at 20:04
  • @Grizzly: So conceptually it's bugged, but the compiler makes it bearable? I didn't know that! –  Aug 08 '12 at 20:06
  • 1
    @AlexBelanger: What? Smart pointer don't have anything to do with the compiler. There is nothing bugged with allocating memory and giving the resulting pointer to an object which will automatically deallocate it when its destroyed (although there are potentially buggy situations if one isn't careful about potential instruction reordering) – Grizzly Aug 08 '12 at 20:08
  • @Alex My answer somewhat addresses this: pointers don’t denote ownership. Setting a single pointer to `0` wouldn’t accomplish much – look at my example code involving `y` and `z`. – Konrad Rudolph Aug 08 '12 at 20:08
  • @Grizzly But modern code also uses very few smart pointers. In fact, in the code I write I can manage almost completely without smart pointers. If client code is using a lot of manual allocations, reconsider your design. Stuff those allocations into backend code (or use backend code which already does this). – Konrad Rudolph Aug 08 '12 at 20:10
  • @KonradRudolph: It was a bad joke actually. Setting the pointer to `0` once the element is destroyed would prevent calling `delete` twice on the same target as deleting NULL is a no-op. –  Aug 08 '12 at 20:11
  • 1
    @Alex I don’t understand the joke then: setting the pointer to `0` would *not* prevent calling `delete` twice on the same *target* – only on the same *pointer*. – Konrad Rudolph Aug 08 '12 at 20:12
  • @KonradRudolph: Okay you have ptr=a, you do delete ptr, a is destroyed, ptr is set to 0, you do delete ptr again, nothing happens (no-op). –  Aug 08 '12 at 20:14
  • @KonradRudolph: Does using less smart pointers make the code more modern? I wouldn't necessarily say so. Personally I would say it entirely depends on what kind of program/code one is writing. – Grizzly Aug 08 '12 at 20:14
  • @KonradRudolph: the joke is about people who would have a code crazy enough to call delete on the same pointer twice, hence the spaghetti reference. –  Aug 08 '12 at 20:15
  • @Grizzly: Take your time to read my comment. I said even if a code is bugged, like some memory isn't freed, you're saying a underlying concept of smart pointers will eventually garbage it ? That's what I understood at least. –  Aug 08 '12 at 20:16
  • 3
    @Grizzly The whole point of a lot of the innovations of C++03 and C++11 (both in the compiler and the libraries) was to reduce the need for manual dynamic memory allocations. If you find yourself using a lot of those, you’re probably doing something wrong. Pervasive use of runtime polymorphic class hierarchies is one such error: they are way overused. C++ offers many features which make such hierarchies redundant in many cases. – Konrad Rudolph Aug 08 '12 at 20:20
  • @AlexBelanger: Once again (the first time being my reaction to your first comment addressed to me) I have absolutely no idea what you are talking about and where the bugged code comes from. KonradRudolph: Or maybe I just need (and have to store) a lot of polymorphic objects since I do need runtime polymorphism for some reason (well maybe I could avoid it, but why make it more complex then necessary?)... You know saying that I'm doing something wrong without knowing my code seems kind of rude. – Grizzly Aug 08 '12 at 20:20
  • @Grizzly Maybe. I didn’t see your code so I can’t judge it. But from experience I can say that runtime polymorphism in C++ is way overused. C++ provides many alternatives which make code *easier*. Most well-designed C++ code tends to use very little runtime polymorphic (*not* none at all, and there are exceptions, e.g. parsers) or can use cleaner alternatives (e.g. Boost’s discriminate unions), and most C++ code which makes heavy use of runtime polymorphism is *not* good C++ code. – Konrad Rudolph Aug 08 '12 at 20:30
8

The first line (int *ptr;) does not allocate any dynamic memory so there is no memory leak. The value you see is uninitialized. It is not a valid pointer. You should not delete the pointer before assigning a value to it. Doing so would be undefined behaviour.

Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
1

No, it's not a memory leak. The difference is that when you say "new int", you're telling C++ to reserve a block of memory to hold an int; if you then lose the pointer to that reserved block, then it can't be recovered, and can't be freed, and therefore it's a leak because it can never be reused.

Just holding some bits in a pointer variable doesn't perform any magic; they're just bits. It's allocating the memory using new that can get you into trouble. Once you've reserved a block, you have to make sure not to lose it.

Ernest Friedman-Hill
  • 80,601
  • 10
  • 150
  • 186
  • @AlexBelanger -- I did. What is it that you think I missed? – Ernest Friedman-Hill Aug 08 '12 at 19:53
  • 1
    I think he is asking why the two outputs printed arn't the same and afraid he just created a memory leak. What I see wrong is that the first pointer isn't initialized so it points to a random memory address... thus the outputs are different, but there's no leak with his code (yet). –  Aug 08 '12 at 19:56
  • Yes, that exactly what my answer says, just like all the other answers on this page say. – Ernest Friedman-Hill Aug 08 '12 at 19:58
  • Well in my opinion it's a way too in-depth answer. Even if it's correct and theses advices are good to keep in mind when playing with pointers, you don't explain to him why he obtained that "weird" result in the first place. –  Aug 08 '12 at 20:00
1

In C/C++, memory is not automatically released. So, yes, if you do this:

 YourType* ptr = new YourType();
 ptr = new YourType();

you will have a memory leak.

But in your case, you don't have a memory leak because the first value is not a valid memory location. It is an uninitialized pointer.

Razvan
  • 9,925
  • 6
  • 38
  • 51