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 GaponReceived on Tue Feb 17 2009 - 08:14:00 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:42 UTC