weeding out c++ keywords from sys/sys

Andriy Gapon avg at icyb.net.ua
Tue Feb 17 01:14:01 PST 2009


on 17/02/2009 03:52 Andrew Reilly said the following:
> Well, code that results in a memory leak (or dangling reference)
> is buggy by definition, but how to avoid it, in general?  I'm
> not about to write some examples for the purpose of this
> discussion, so google searches will have to do.
> 
> The first google search that I did for "C++ argument promotion
> temporary objects" came up with this link:
> http://www.icce.rug.nl/documents/cplusplus/cplusplus09.html
> 
> If you skip down to the StringArray example, you can see that
> a new String object is automatically constructed to cast the
> char* to fit the String &operator[](size_t idx) method.  Now,
> in this instance the constructed object has somewhere to go: a
> reference is being stored in the array.  So the temporary object
> must have been constructed on the heap.  But other methods on
> other objects may require String arguments, invoking the same
> constructor, but they might not record the reference and so it
> won't be cleaned up later.  Or will it?

Actually in that I example I see only definition of the interface and 
nothing about its implementation. The fact that that "String 
&operator[](size_t idx)" operator returns a reference to String doesn't 
mean that the class stores references. In fact, if return type of this 
operator was just "String" then it would mean that it returns a copy of 
a String.
So it's impossible to judge what "the code that isn't there" would do.
We could consider how vector<string> works, which is very close to that 
interface (mucho simplified).
First of all, actual array of string objects is stored in the vector.
Then, in this case no temporary object is needed at all, because string 
has an assignment operator from const char *, which means that a string 
object knows how update itself when it is being assigned a const char * 
value.

Also please see here:
http://www.parashift.com/c++-faq-lite/references.html
Section 8.3.

> Conversely (and perhaps you will see my confusion): this other
> paper:
> http://codewrangler.home.comcast.net/~codewrangler/tech_info/cpp_compiler_tips.html
> Under the section "Lifetime of Temporary Unnamed Objects" there
> is a discussion about such temporary objects being reclaimed by
> the language runtime as they go out of scope of the expression
> in which they were created.  So that sounds like either stack
> allocation or heap allocation with explicit destructors inserted
> when leaving scope.  Either way, that would appear to render the
> StringArray example above comprehensively broken, no?  (The
> array would contain a dangling reference when the temporary
> String object is reclaimed at the end of the expression scope.)


In general the following hold true:
1. temporary objects always have automatic scope which means that they 
are destroyed as soon as a scope where they were needed is left; 
compiler generates that code;
2. compiler would not allow to assign a pointer to a temporary object; 
it only allows to initialize a const reference with a temporary object, 
in which case the scope of the temporary is extended to be the same as 
the scope of that reference variable.
3. constructor of a temporary variable can, of course, allocate 
something on the heap (e.g. some sort of a buffer); its destructor must 
deallocate that memory; if it doesn't, then this just buggy code, 
nothing to do with temporaries.

> This issue is, I believe, undecidable at compile time, and
> goes by the name "escape detection".  It is why *all* modern
> object-oriented languages require garbage collection.  Some
> recent JIT runtime systems go to a great deal of effort to prove
> that references to some objects do not "escape" the block, and
> so can be stack-allocated and eagerly collected.  That requires
> whole-program analysis, which is something that a JIT can fudge,
> but which a C++ compiler doing separate-compilation can't.

No, no. C++ has stricter and simpler rules. It tries very hard to not 
allow a programmer to let any pointers/references to temporary objects 
escape. Of course, a sufficiently good programmer can still manage to 
make it happen, but then it's a programmer's problem - the temporary 
object would still not escape and be destroyed, the pointer/reference 
would point to garbage.
It's like in C - you can return a pointer to a struct on stack, but that 
wouldn't make that struct magically be transfered to heap and persist, 
it would just make the returned pointer point to bad data.

You might be also confused about what 'reference' in C++ is. In fact, 
Java references are very much alike C++ pointers (e.g. can be null, can 
be re-pointed). C++ references (when not abused through nasty tricks 
possible due to C compatibility) are just permanently-bound aliases.
http://en.wikipedia.org/wiki/Reference_(C%2B%2B)

I hope I managed to explain at least something, not made too many 
mistakes (I am not a big C++ expert recently) and not added to the 
confusion :-)

-- 
Andriy Gapon


More information about the freebsd-current mailing list