On Sun, Jun 17, 2012 at 4:02 PM, john skaller <skal...@users.sourceforge.net> wrote: > The failure of the strdict-01 regression test on Windows has > again highlighted the design fault in strings .. both Felix and C++. > > When you call > > char const *p = string("hello").c_str(); > > in C++ you have a dangling pointer p. The call succeeds because > string("hello") is a non-const rvalue, but there's no mechanism > in C++ for a method to require an lvalue object: you can insist > that a function argument is an lvalue, but not the object of a non-static > member function.
That was fixed in C++11. The syntax is something like: struct S { void f() &; }; where the default is that *this can be either an lvalue or an rvalue, and users can write "&" or "&&" to restrict to one or the other. Compilers have been a touch slow implementing this though. However: in C++ it's often convenient and correct to call c_str() on a temporary -- e.g., printf("...%s\n", (string("this") + " and that").c_str()). The temporary isn't destroyed until after the printf call returns, and all is well. > Consequently the string("hello") temporary may evaporate immediately > after p is assigned to its internal buffer, and the destructor deletes > the storage, leaving p dangling. > > In Felix, this means calling > > "Hello".cstr > > is more or less guaranteed to be invalid. It is not even valid > to do this: > > fun f(x:string) = { > g (strdup (x.cstr)); > ... > > because "x" is a val, and vals can be either eagerly > or lazily evaluated. If the function above is inlined, > a call such as > > f("hello") > > can reduce to > > g ( strdup ("hello".cstr) ) > > and the pointer can be left dangling even before strdup > is called. > > Note this problem is not limited to cstr -- it applies to STL > begin() and end() too. Anything that gets a pointer into any > data structure can have the pointer invalidated if the > data structure is destroyed, and if the data structure is > a temporary that can happen very quickly. > > It turns out the Microsoft compiler MSVC++ is much more > aggressive about this than gcc or clang, which presumably > are dumbed down to cope with dumb end user legacy code: > they appear to remove temporaries at the end of the containing > statement, instead of immediately after use. C++ specifies exactly when the temporaries are destroyed, specifically at the end of the "full expression", and the only compiler I've seen deviate from it recently (within the last decade) was Sun's. The exception is when copy/move-elision reduces the number of objects, as you've noted below. > Of course the converse may be possible too: gcc aggressively > removes copying whereas MS doesn't, this would lead to the > same situation because gcc would then be keeping a single value > around with the lifetime of the original extended to the copy > that it didn't make. Something along those lines is certainly possible. -- James ------------------------------------------------------------------------------ Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ _______________________________________________ Felix-language mailing list Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language