On 19/06/2012, at 6:42 AM, James Dennett wrote:

> 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.

Ah. That's N2439 by the look of it and it's been in clang since
version 2.9 (latest stable is 3.1),. Gcc pages says:

Ongoing C++11 Development

Rvalue references for *this

Bronek Kozicki has been working on this feature.

> 
> 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.

Yep, Felix does this in C++ implementations all the time, safely.
But the Felix function 

        cstr x

cannot do this safely: it then depends on the user being careful
(i.e. it isn't safe), and that's MUCH harder to do in Felix than in C++
because Felix has much "weaker" semantics to allow much
better optimisation than C++ can dream of. It's possible to control
this in Felix .. but that's the problem: you actually have to actively
control it.

Just to explain, in C++

        void f(x:string) { ... }

in the body of f, x is an object with a determinate lifetime.
Even if C++ compiler inlines the function, or does optimisations,
it must respect these semantics. 

In Felix it is the same with

        fun f(var x:string) = { .. }

but if you write instead:

        fun f(x:string) = { .. }

it means

        fun f(val x:string) = {  .. }

which tells Felix to treat x as a value, not an object. Felix is allowed to
do eager evaluation like the "var" case and assign the argument
to a variable, OR, it is allowed to just replace "x" in the body of the
function with the actual argument.  If the function f
is inlined it is likely it will use the lazy evaluation strategy.
[Because it's almost always faster]

It may also factor your code. So you may end up with:

        char * p = string("hello").c_str();

which has unspecified semantics and will probably corrupt your
program. Indeed this actually DOES happen.


> 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.

Indeed, but the Felix compiler generates C++ code without respecting
the notion of "full expression". The compiler considers itself free to
factor any expression into a series of assignments and a simpler
expression, that is, roughly "Three address code":

        f ( g ( h (x)))

can be changed to 

        hx = h (x)
        ghx = g (hx)
        f (ghx)

This is safe in Felix, because Felix does not have any references:
we only have values, and use pointers for objects. Felix pointers
are garbage collected.

the problem is interfacing to C and C++ where there is "hidden"
internal pointers that C++ allows to be stolen, such as with
most STL containers including strings.

Those pointers are not managed by Felix GC, and they're
not managed by C++ either. They have to be managed by the
programmer, so they're not safe.

This normally isn't a problem in Felix UNLESS the programmer
makes a binding of a C/C++ data type. in this case the programmer
is ME, binding the Felix string type to the C++ string type.

Unfortunately we HAVE to support char* string types as well
as C++ string types because we have to interface with C code ..
exactly the same reason C++ has to support it too.


--
john skaller
skal...@users.sourceforge.net
http://felix-lang.org




------------------------------------------------------------------------------
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

Reply via email to