4

Yes, I'm one of those fellows that is learning C++ coming from Java, being spoiled with an automatic garbage collector. There's a particular situation where I'm wondering whether I'm leaking memory or not. Let's consider in C++:

bool *test = new bool(false);
test = new bool(true);
delete test;

Am I leaking memory here? Or should I first call delete before assigning a new value? Like this:

bool *test = new bool(false);
delete test;
test = new bool(true);
delete test;

My gut feeling tells me the first is right, as the pointer test points at the same address in memory, and assigning a new value to its variable, will not change this address. Or does the new operator allocate a different address in memory? Can anyone give me a clue, or did I get it wrong all together?

Louis Marascio
  • 2,629
  • 24
  • 28
Peppivankokki
  • 41
  • 1
  • 2
  • 11
    Re: "Yes, I'm one of those fellows that is learning c++ coming from Java." Then I highly recommend picking up [a good introductory C++ book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) and pretend you've never learned Java. C++ is not Java. Attempting to program like Java in C++ will only lead to tears and frustration. [It's like using RegEx to parse HTML](http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454). – In silico Aug 08 '11 at 13:28
  • 4
    "Spoiled" is a euphemism, if I have ever heard one. – Kerrek SB Aug 08 '11 at 13:28
  • It's quite possible that's exactly what he's doing. – Louis Marascio Aug 08 '11 at 13:32
  • Do you really need the 'bool' to be allocated on the heap? Especially single values of build-in types are very uncommon to be allocated on the heap. In a normal C++ program "new" is used much rarer than in a common Java program! – Ludger Sprenker Aug 08 '11 at 13:44
  • C++ has its own GC system that acts at a much finer grain than Javas. You just have to use it. Use `std::shared_ptr` rather than `int*` and all your problems go away as the garbage collector now works. But you don;t even need to dynamically allocate the objects. Just use `bool` rather than `bool*` – Martin York Aug 08 '11 at 15:34
  • see: http://stackoverflow.com/questions/5174725/how-do-you-explain-c-pointers-to-a-c-java-developer/5174827#5174827 – Martin York Aug 08 '11 at 15:35
  • @Martin: Can we please not suggest smart pointers? You need to learn to walk before you can run. – MGZero Aug 09 '11 at 14:59
  • @MGZero: I think that comment is silly. You should learn to use smart pointers first. When you have the basics down then you can experiment with the dangerous stuff like pointers. If we were learning C then my advice would be the other way around but C++ is **NOT** C nor should it be treated as such. Learning C first is (in my opinion) a mistake as you get in the wrong habits for developing C++ code. – Martin York Aug 10 '11 at 17:47
  • @Martin: Although true raw pointers are more dangerous, I find it a bit strange to call smart pointers the basics as they're an implementation of raw pointers. Matter of opinion, I guess. – MGZero Aug 10 '11 at 18:53
  • @MGZero: What are you talking about. `Smart pointers are an implementation of raw pointers` makes absolutely no sense. Using smart pointers rather RAW pointers makes pointer behave like pointers in nearly every other language (as the smart pointer is a wrapper object) and thus makes them intuitive to use for anybody coming from any other programming background (except C). How smart pointers are implemented is an irrelevant implementation details the fact they contains pointers is beside the point you do not need to know this to use them. – Martin York Aug 10 '11 at 19:21
  • @MGZero: Since modern C++ code should contain zero (none nada not a single one) pointers I find it a waste of time teaching the concept of pointers to beginners (they need to learn to walk first). Once they understand the basics of how to use objects we can teach them how to use pointers to implement interesting objects (that;s when they learn to run with sharp pointy objects). I think you have your concept of running/walking completely backwards as it pertains to C++ usage (your ideas pertain to people that want to learn C). – Martin York Aug 10 '11 at 19:24
  • @Martin Actually, it does make sense. You said it yourself, "as the smart pointer is a wrapper object." So you must agree obviously that behind the scenes of a smart pointer is a raw pointer (maybe I used the wrong word earlier). I also don't see how knowing how to use a pointer is irrelevant. Ask someone new to pointers to dereference their smart pointer, there's a good chance they won't have a clue what you're talking about. Just because the pointer is smart, doesn't mean the programmer is (sorry, it was there, I had to rofl). – MGZero Aug 10 '11 at 19:34
  • @MGZero: No. Still does not make sense. Please feel free to join the [C++ chat room](http://chat.stackoverflow.com/rooms/10/loungec). There are currently several smart people in there that will explain the concepts. – Martin York Aug 10 '11 at 19:40
  • @Martin If you're just going to say it doesn't make sense from this point on without any other reason and refer me to other people, then I'm not even going to waste our time. I was actually enjoying this little discussion of ours, btw. Gave me something to do at work haha – MGZero Aug 10 '11 at 19:50

7 Answers7

6

Yes you are leaking, and the c++ way to do it is:

bool test = false;
test = true; 

// ta-da - no leak.

You could do the second approach - however you're likely to draw lots of frowning...

Nim
  • 33,299
  • 2
  • 62
  • 101
  • and what if he needs to later `return test` ? – amit Aug 08 '11 at 13:31
  • @amit, what's that got to do with anything? – Nim Aug 08 '11 at 13:31
  • 2
    @amit well, for built-in types I'd stick with Nim's option. – Vinicius Kamakura Aug 08 '11 at 13:32
  • he probably uses dynamic allocation because static allocation cannot provide an answer. `return test` [or in your example `return &test`] will result in undefined behavior when later accessing `test`. – amit Aug 08 '11 at 13:34
  • 1
    @amit: And why would a person return a reference to a local variable? – In silico Aug 08 '11 at 13:35
  • @hexa: so am I, but it seems like a toy example. the OP [or future reader] might understand from this answer that he should ALWAYS use static allocation, which is obviously wrong. – amit Aug 08 '11 at 13:35
  • @In silicio: exactly what I meant, the OP is probably using dynamic allocation for a reason, the original example was NOT a local variable. – amit Aug 08 '11 at 13:36
  • This answer implies one should always use static allocation instead of dynamic allocation. this is obviously not always possible, this is what I meant in my comments. – amit Aug 08 '11 at 13:38
  • @amit - please read the answer carefully - did I mention *static* allocation anywhere? In C++ you should default to *stack* (read automatic) allocation where possible, and dynamic (through smart pointers) where not - the OP appears to be a beginner - smart pointers are probably a little way off yet... furthermore, to return a built-in type, I cannot think of any reason why you would return a dynamically allocated instance... – Nim Aug 08 '11 at 13:38
  • 1
    @amit: Correct. I think what Nim is trying to get at is that automatic allocation of variables are *preferable* to dynamic allocation. – In silico Aug 08 '11 at 13:39
  • 1
    @In Silicio, Nim: I agree static allocation is preferable when possible, but it is not always the case. it seems to me the OP is indeed a beginner, and he's currently learning dynamic allocation. a solution of "use static allocation" when learning dynamic allocation is not a solution, in my opinion. – amit Aug 08 '11 at 13:41
  • 2
    @amit It seems more likely in my mind, that coming from reference-counted, garbage-collected, "new everything" Java, the OP isn't used to the idiomatic C++ way of declaring local variables. – Mark B Aug 08 '11 at 13:43
  • @Kerrek SB - care to expand that comment? – Nim Aug 08 '11 at 13:45
  • @Nim: smart ass remark about the Standard not mentionning stack (apart from the STL structure) I'd guess :/ – Matthieu M. Aug 08 '11 at 13:47
  • @Nim: C++ has no notion of "stack" and "heap" -- what matters is the storage class, "automatic" vs. "dynamic" (vs. "static"). Experienced C++ers are usually happy to conflate the two, but when talking to a recovering Java programmer I thought it'd be apropos to be clear about this. – Kerrek SB Aug 08 '11 at 13:57
  • @Kerrek - hehe - see, now your comment makes more sense to someone reading this far down in the comments! ;) – Nim Aug 08 '11 at 14:02
5

Yes, exactly, you have to delete before you overwrite the address. Or better yet allocate on stack or use a smart pointer.

sharptooth
  • 167,383
  • 100
  • 513
  • 979
1

You have indeed been spoiled.

The problem is that you do not differentiate between an address and a variable.


bool *test = new bool(false);
  • Allocate space with automatic duration for test
  • Allocate space with dynamic duration for a bool
  • Write false into this space
  • Store the address of this space into test

test = new bool(true);
  • Allocate space with dynamic duration for a bool
  • Write true into this space
  • Store the address of this space into test (the address previously stored is ruthlessly discarded, since it is not stored anywhere else, the memory it points to can never be reclaimed, which means you have a leak).

delete test;
  • Read the address stored into test
  • Deallocate the space at this address

My gut feeling tells me the first is right, as the pointer test points at the same address in memory, and assigning a new value to its variable, will not change this address. Or does the new operator allocate a different address in memory?

Semantically, you should consider that new always return an address to a new space in memory (Obviously false, as memory is reused). This is why each call to new need to be matched by exactly one call to delete.

Therefore your gut feeling is wrong, new does not create "just" a variable. If you are coming from Java, this may be shocking indeed, and you'll need a strong tutorial to grasp the finer points of programming.

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

Yes, you are leaking memory. For every new there should be a subsequent delete. If you overwrite a pointer with a new address then you lose the opportunity to pair the allocation with a delete.

Louis Marascio
  • 2,629
  • 24
  • 28
0

Yes, your first example is actually leaking memory. Every call to new must have a matched call to delete (unless the new failed).

In C++ the normal way to do what you appear to be trying to do is to simply declare the bool locally:

bool b = truel
b = false;

If however you actually need dynamic allocation for some reason, there are smart pointers that manage the memory so you don't have to worry about calling delete. You can look up scoped_ptr, unique_ptr and shared_ptr.

Finally, C++ has a great standard library that handles many possible containers and algorithms, preventing you from having to reinvent them and saving you from having to deal with dynamic allocation in a wide variety of cases.

If you're serious about learning C++ I would pick out one of the books from the SO C++ book list and learn from the ground up rather than trying to transfer Java idioms to C++ (it just won't work well).

Mark B
  • 95,107
  • 10
  • 109
  • 188
0

bool is a built in datatype.Why do you need to allocate memory like that?You can easily allocate on stack

Poulami
  • 1,047
  • 3
  • 13
  • 27
0

Yes, you are leaking memory in the first case. The second way is the proper way to do it. In your first case...

When you call new the second time, the first allocation goes out of scope, but still exists. In Java, this is fine because the GC will clean it up for you. However, in C++, there's no such way with raw spointers.

Each call to new must also have a call to delete at some point. Also, after you delete a pointer, set it to null or 0. This will prevent you from accidently deleting invalid memory.

MGZero
  • 5,812
  • 5
  • 29
  • 46