You are not logged in.

#1 2005-03-23 17:00:54

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

heap/stack, RVO, and destructors

yes, wonderful topic name...

I always wondered if the following (c++) code would work:

std::string& foo()
{
   std::string* s = new std::string("bar");
   return *s;
}

void test()
{
   std::string s = foo();
} //does s get properly destroied here?

the problem is as follows:
in test(), s is declared as a stack (auto) variable...
in foo(), s is created on the heap, and returned by reference, instead of by pointer...
technically, this code is sound... however I don't know if proper destruction takes place... will RVO (return value optimization) take care of it?

Offline

#2 2005-03-23 17:31:32

i3839
Member
Registered: 2004-02-04
Posts: 1,185

Re: heap/stack, RVO, and destructors

#include <string>
#include <unistd.h>

static char b[10];

std::string& foo()
{
   std::string* s = new std::string("bar");
   return *s;
}

void test()
{
   std::string s = foo();
}

int main()
{
    test();
    read(0, b, 10);
    for (int i = 0; i < 100000; ++i){
        test();
    }
    read(0, b, 10);
    return 0;
}

Eats about 4 Mb here, so nope.
That that "std::string s = foo();" is allowed is just sick...
References in C++ are only confusing, just use pointers.

In case you wonder, the read's are there so you have time to look at the memory usage in top.

Offline

#3 2005-03-23 17:34:06

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: heap/stack, RVO, and destructors

i3839 wrote:

References in C++ are only confusing, just use pointers.

I can't believe you said that 8) They're the same thing...

hmmm actually, seeing as you tried this (no C compiler at work)... try

void test()
{ std::string &s = foo();
}

instead....

Offline

#4 2005-03-23 17:39:04

Dusty
Schwag Merchant
From: Medicine Hat, Alberta, Canada
Registered: 2004-01-18
Posts: 5,986
Website

Re: heap/stack, RVO, and destructors

*taps his trusty garbage collector knowingly*

Offline

#5 2005-03-23 17:44:52

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: heap/stack, RVO, and destructors

Dusty wrote:

*taps his trusty garbage collector knowingly*

*stares at http://www.hpl.hp.com/personal/Hans_Boehm/gc/ *

Offline

#6 2005-03-23 17:47:00

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: heap/stack, RVO, and destructors

i3839 wrote:

References in C++ are only confusing, just use pointers.

Bjarne Stroustrup wrote:

It's always easier to say what not to do, rather than what to do, so I'll start that way. A lot of people see C++ as C with a few bits and pieces added. They write code with a lot of arrays and pointers. They tend to use new the way they used malloc. Basically, the abstraction level is low. Writing C-style code is one way to get into C++, but it's not using C++ really well.

pointers in C = good
pointers in C++ = poor form

Offline

#7 2005-03-23 18:40:59

Dusty
Schwag Merchant
From: Medicine Hat, Alberta, Canada
Registered: 2004-01-18
Posts: 5,986
Website

Re: heap/stack, RVO, and destructors

hey, I can throw quotes around too!

Bjarne Stroustrup wrote:

Within C++, there is a much smaller and cleaner language struggling to get out

anonymous wrote:

Yeah, its called Java

of course, I'm not starting a language war here, because I think C++ is cool. I just don't know it. very well.

Dusty

Offline

#8 2005-03-23 20:10:05

i3839
Member
Registered: 2004-02-04
Posts: 1,185

Re: heap/stack, RVO, and destructors

std::string s = foo();

You ask for a string, and you get a reference? Am I missing something? How is that confusing thing better than:

std::string* s = foo();

if you return there it's pretty clear that s is just a pointer which is never autocleaned because it is on the stack, no stinky reference hiding the pointer nature of the thing away. In Java references are fine because they have garbage collection, there it doesn't matter if you leak stuff everywhere, but obscuring the memory handling in C++ where you need to keep it clean yourself is asking for problems. Now if you have a little static class with does autoreference counting or something then it's fine to keep things hidden, but you don't have that excuse often. The only difference is their syntax, one is very clear, other is obscuring. So how can pointers in C++ be bad while references aren't? Hiding things behind abstraction is fine, but not when you forgot to implement that abstraction properly, which a lot of people seem to forget, hoping that just using C++ and repeating certain mantra's is enough to cover their ass.

Offline

#9 2005-03-23 20:20:23

cactus
Taco Eater
From: t͈̫̹ͨa͖͕͎̱͈ͨ͆ć̥̖̝o̫̫̼s͈̭̱̞͍̃!̰
Registered: 2004-05-25
Posts: 4,615
Website

Re: heap/stack, RVO, and destructors

useless offtopic post: I hate java.


"Be conservative in what you send; be liberal in what you accept." -- Postel's Law
"tacos" -- Cactus' Law
"t̥͍͎̪̪͗a̴̻̩͈͚ͨc̠o̩̙͈ͫͅs͙͎̙͊ ͔͇̫̜t͎̳̀a̜̞̗ͩc̗͍͚o̲̯̿s̖̣̤̙͌ ̖̜̈ț̰̫͓ạ̪͖̳c̲͎͕̰̯̃̈o͉ͅs̪ͪ ̜̻̖̜͕" -- -̖͚̫̙̓-̺̠͇ͤ̃ ̜̪̜ͯZ͔̗̭̞ͪA̝͈̙͖̩L͉̠̺͓G̙̞̦͖O̳̗͍

Offline

#10 2005-03-23 20:57:48

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: heap/stack, RVO, and destructors

i3839 wrote:

So how can pointers in C++ be bad while references aren't? Hiding things behind abstraction is fine, but not when you forgot to implement that abstraction properly, which a lot of people seem to forget, hoping that just using C++ and repeating certain mantra's is enough to cover their ass.

you sound like a C programmer... obviously, my example is not normal... it is not normal usage.
However, if you look at the function signature, it specifically lists "std::string&" as the return type... indicating a reference as easilly as one indicates a pointer.... however, the usage differs... it's all a matter of knowing what's going on.  In the pointer world, you usually have to understand pointer arithmetic (in the complicated cases) and when to delete (free) it.  In the reference world, you need to understand the memory "scope" of the variable...

pointers are evil in c++ because it requires you to put effort into memory management... references are just as fast when used correctly... so it's win-win

Offline

#11 2005-03-23 20:58:55

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Offline

#12 2005-03-23 21:29:01

i3839
Member
Registered: 2004-02-04
Posts: 1,185

Re: heap/stack, RVO, and destructors

Let's summarize what's going on:

Pointers are evil in C++ because it forces you to do memory handling. Though when replacing that pointer with a reference you get an easily overlooked memory leak.

Perhaps the example you gave was plain wrong and a counter argument for your noble case, and a reference getting out of scope does free up memory, sometimes. But to me it looks like you should use a language with no memory management at all if you continue throwing your arguments around. So go hug Java or something. ;-)

And yes, I'm a C programmer to the core. But I must say that I first learned C++ before C, and then found all C++'s weirdness only counter-productive. When getting free from the "C++ is just C but better"-dogma I was finally happy, by ditching C++ and embracing C.

C++ isn't evil, but keep your references and STL away from me, thank you very much.

Offline

#13 2005-03-23 21:54:54

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: heap/stack, RVO, and destructors

well, the only real response I have is that, the only reason there was a leak like that was due to the fact that I used a pointer in the first place [new string()]...

And I first learned C, then C++, so maybe that's the way of it... whatever you learn second?

And I don't think C is evil... but it *is* ugly (look at some strtok or strrchr loop functions.... blegh).

However, I will say one thing when it comes to memory usage:
C uses no memory management, forcing the developer to code it into the program
C++ uses internal memory management
Java uses no memory management either (!!), but has very efficient clean-up mechanisms in place to take care of it

Offline

#14 2005-03-23 22:17:16

i3839
Member
Registered: 2004-02-04
Posts: 1,185

Re: heap/stack, RVO, and destructors

Every language can be ugly, most code is ugly. And who knows, perhaps at average people write less ugly code in Java than in C.

Perhaps I'm missing some hidden magick of references, but you said they were the same as pointers, and you made a new object and got a reference, no pointer in sight, so how can you blame pointers?

As for the memory management, what "internal memory management"? If you get data with new you need to free it yourself, either directly or indirectly (delete(this)?). All the memory management needs to be build into the classes as far as I can tell, or did C++ change so much recently? Java is bytecode stuff, easy for them to implement garbage collecting. Only useful thing in C++ are destructors, and Java misses them (garbage collector must be taken very litterally in Java).

Offline

#15 2005-03-23 22:53:42

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: heap/stack, RVO, and destructors

i3839 wrote:

Perhaps I'm missing some hidden magick of references, but you said they were the same as pointers, and you made a new object and got a reference, no pointer in sight, so how can you blame pointers?

that's excatly it... "new" returns a pointer... technically one should just [return string("foo");] without the "new" - and RVO then takes the construction into account so it's not done twice (once on the return line, then a copy constructor when the actual return does it's job)

i3839 wrote:

As for the memory management, what "internal memory management"? If you get data with new you need to free it yourself, either directly or indirectly (delete(this)?). All the memory management needs to be build into the classes as far as I can tell, or did C++ change so much recently?

I was talking specifically about the STL... which is C++, as much as some people don't like to admit... anyone can write a class that has resource issues in general... hell you can do it with database connections in java (and C#)

When you initialize an std::string, it calls new internally... and actually stores just the begin/end pointers, but it takes care or it's own resources...
the pseudo-techincal term is "RAII" (Resource Acquisition is Initialization) - constructor calls new, destructor deletes... it's all internal... when consuming that class, you never need worry about memory management if done correctly.

Offline

#16 2005-03-23 22:58:45

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: heap/stack, RVO, and destructors

for the record, this is the proper version of the snippet in the original post:

std::string foo()
{
   std::string s("bar");
   return s;
}

void test()
{
   std::string s = foo();
}

the difference is there are no pointers being thrown around... RVO takes care of the potential copy-construction on return....

think about it this way: using the stl should be just like using primitives... (most of the time) you wouldn't malloc() an int... you'd do something like this [same code, with std::string replaced with int]

int foo()
{
   int i = 5;
   return i;
}

void test()
{
   int i = foo();
}

Offline

#17 2005-03-23 23:44:57

i3839
Member
Registered: 2004-02-04
Posts: 1,185

Re: heap/stack, RVO, and destructors

phrakture wrote:

I was talking specifically about the STL... which is C++, as much as some people don't like to admit...

Yes, C++ without STL isn't worth it, and STL is too ugly to want it, IMHO.

the pseudo-techincal term is "RAII" (Resource Acquisition is Initialization) - constructor calls new, destructor deletes... it's all internal... when consuming that class, you never need worry about memory management if done correctly.

That's what I said: it's still there, but hidden away if done properly. So if you write a class you still need to do the memory handling for at least your own class. A problem is that you can't see from the outside who needs to handle the memory of a class. Memory handling isn't a big deal anyway...

Offline

#18 2005-03-23 23:59:11

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: heap/stack, RVO, and destructors

i3839 wrote:

Yes, C++ without STL isn't worth it, and STL is too ugly to want it, IMHO.

no way... check this out:

using namespace std;
int add_one(int i) { return i++; }
int main()
{
    vector<int> v;

    //fill v with ints from stdin until parsing fails (or ^D)
    copy(istream_iterator(cin),istream_iterator(),back_inserter(v));

    //add one to all elements of v
    transform(v.begin(),v.end(),&add_one);

    //output it all
    copy(v.begin(),v.end(),ostream_iterator(cout));

    //output the sum
    cout << accumulate(v.begin(),v.end(),0);

    return 0;
}

IMHO, that's totally more elegant than *most* other ways of doing it, but that's just personal opinion....

I also think python is elegant, so take it with a grain of salt (most don't)

Offline

#19 2005-03-24 00:32:43

i3839
Member
Registered: 2004-02-04
Posts: 1,185

Re: heap/stack, RVO, and destructors

That you can do arbitrary weird things in a couple of unclear lines with STL code doesn't mean that STL is very clear... That also doesn't mean that it's less clear than doing the same without STL, but with other premade library functions (or classes). Anyway, stuffing 15 function calls into 6 lines of code is an achievement in itself.

The code doesn't compile, also not after adding:

#include <vector>
#include <string>
#include <iostream>
#include <istream>

Next time please post code that compiles so it can be tested if it does what it's supposed to do.

Offline

#20 2005-03-24 01:30:49

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: heap/stack, RVO, and destructors

bah, picky aren't we? I wrote it in a text box in firefox... i never said it'd be perfect.... it was just an example

I missed the template parameters on the stream_iterators....
and forgot the output arg to transform.... this works
(use "g++ filename.cpp -o filename)

#include <vector>
#include <iostream>
#include <algorithm>
#include <numeric>

using namespace std;
int add_nine(int i) { return i+9; }

int main()
{
   vector<int> v;

   //fill v with ints from stdin until parsing fails (or ^D)
   copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(v));

   //add one to all elements of v
   transform(v.begin(),v.end(),v.begin(), add_nine);

   //output it all
   copy(v.begin(),v.end(),ostream_iterator<int>(cout,"n"));

   //output the sum
   cout << "sum:" << accumulate(v.begin(),v.end(),0) << "n";

   return 0;
}

edit: note on the default input handling - it is only parsed on a cr, so you can either do "1 2 3 4 5<cr>" or "1<cr>2<cr>3<cr>4<cr>5<cr>" to get those numbers in there... it will stop reading on a ctrl+d (EOF) or on a failed parse (1 2 3 4 5 abcde)

Offline

#21 2005-03-24 01:40:57

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: heap/stack, RVO, and destructors

i3839 wrote:

Anyway, stuffing 15 function calls into 6 lines of code is an achievement in itself.

yeah it can be optimized (vector<int>::iterator b = v.begin()) but the compiler will handle that just fine...

Offline

Board footer

Powered by FluxBB