November 11, 2009
grauzone wrote:
> Walter Bright wrote:
>> grauzone wrote:
>>> In this case, the semantic difference between safe and unsafe functions will cause trouble, and you'd eventually end up imposing the "safe" semantics upon unsafe functions.
>>
>> May be.
> 
> Returning a slice to a local static array would be fine in safe mode, but lead to silent corruption in "unsafe" mode. I think everyone would assume that, if something works in safe mode, it should also work in unsafe mode.

It's a good point.


> So, it's really a "must", or is there some other way around it?

I don't know.
November 11, 2009
Walter Bright schrieb:
> Consider the code:
> 
>   @safe:
>     T[] foo(T[] a) { return a; }
> 
>     T[] bar()
>     {
>         T[10] x;
>         return foo(x);
>     }
> 

If D would have something like a slice-info which could be returned instead of the slice itself, then foo would be safe.

slice-info would be something like a struct/Tuple storing the start and end index.

That applied onto the original array gives the slice.

SliceInfo foo( T[] a){
  // do something, resulting in e.g. a[2..6]
  return SliceInfo(2, 6);
}

T[] bar(){
	T[] x = new T[10];
	return x[foo(x)]; // safe compile OK
}

T[] bar(){
	T[10] x;
	return x[foo(x)]; // safe error, because x slice escapes
}

This shifts responsibility of memory safety to the caller with little extra effort.
November 12, 2009
Walter Bright wrote:
> Consider the code:
> 
>   @safe:
>     T[] foo(T[] a) { return a; }
> 
>     T[] bar()
>     {
>         T[10] x;
>         return foo(x);
>     }
> 
> Now we've got an escaping reference to bar's stack. This is not memory safe. But giving up slices is a heavy burden.
> 
> So it occurred to me that the same solution for closures can be used here. If the address is taken of a stack variable in a safe function, that variable is instead allocated on the heap. If a more advanced compiler could prove that the address does not escape, it could be put back on the stack.
> 
> The code will be a little slower, but it will be memory safe. This change wouldn't be done in trusted or unsafe functions.

Enter random annotation which asserts the function is allocated on the stack?
November 12, 2009
Walter Bright:

>I thought of that, but I think it's too restrictive.<

I agree. A possible solution to this problem (Ellery Newcomer may have said the same thing): in safe functions require locally some kind of annotation that turns that into a safe heap allocation (and at the same time it denotes such heap allocation in a visible way). In unsafe functions such annotation is optional, while in safe code you must put it if you want to use the feature.


>"system" sounds good.<

"unsafe" is still good that purpose because it's like the __ for gshared: it's designed on purpose to look less nice.

Bye,
bearophile
November 12, 2009
bearophile wrote:
>> "system" sounds good.<
> 
> "unsafe" is still good that purpose because it's like the __ for
> gshared: it's designed on purpose to look less nice.

"Unsafe" is also a misnomer. It implies the code is broken. I don't like it.
November 12, 2009
Walter Bright wrote:
> bearophile wrote:
>>> "system" sounds good.<
>>
>> "unsafe" is still good that purpose because it's like the __ for
>> gshared: it's designed on purpose to look less nice.
> 
> "Unsafe" is also a misnomer. It implies the code is broken. I don't like it.

There are definitely functions which are dangerous if you pass them invalid parameters. ie, "use at own risk" -- any function which uses them needs to add its own tests. I think something which implies "you should think before you use this function" is reasonable.

I don't care at all what the name is, however. @system would be OK.

November 12, 2009
On Wed, 11 Nov 2009 16:47:10 -0500, Walter Bright <newshound1@digitalmars.com> wrote:

> Consider the code:
>
>    @safe:
>      T[] foo(T[] a) { return a; }
>
>      T[] bar()
>      {
>          T[10] x;
>          return foo(x);
>      }
>
> Now we've got an escaping reference to bar's stack. This is not memory safe. But giving up slices is a heavy burden.
>
> So it occurred to me that the same solution for closures can be used here. If the address is taken of a stack variable in a safe function, that variable is instead allocated on the heap. If a more advanced compiler could prove that the address does not escape, it could be put back on the stack.
>
> The code will be a little slower, but it will be memory safe. This change wouldn't be done in trusted or unsafe functions.

This sounds acceptable to me.  In response to others making claims about modifying behavior, you can get a safe function that can use unsafe behavior by using @trusted if you wish.

I'm assuming this behavior translates to local non-array variables?

Can we allow the scope variable hack that is afforded for delegates:

@safe int sum(scope int[] a) { int retval = 0; foreach(i; a) retval += i; return retval;}

This would not result in a heap allocation when called with a static array.

-Steve
November 12, 2009
== Quote from Don (nospam@nospam.com)'s article
> There are definitely functions which are dangerous if you pass them
> invalid parameters. ie, "use at own risk" -- any function which uses
> them needs to add its own tests. I think something which implies "you
> should think before you use this function" is reasonable.
> I don't care at all what the name is, however. @system would be OK.

Yeah, and sometimes the functions that are unsafe when passed invalid parameters aren't obvious.  Granted this is an extreme corner case, but I recently debugged an access violation that was occurring in a well-tested sorting function that I would have definitely annotated @trusted.  I was sorting on floating point keys, and it turned out there were NaNs in there and the sort function assumed that there would be a proper total ordering.  If the pivot element was a NaN, it would therefore enter an endless loop because there was nothing in the array that was <= the pivot, until it read past the end of the array.  This was a latent bug for a long time and only showed up when I ran the program with parameters that generated NaNs.

Of course the real solution here is to get rid of the #()&# lack of total ordering
for floats.
November 12, 2009
Walter Bright wrote:
> Consider the code:
> 
>   @safe:
>     T[] foo(T[] a) { return a; }
> 
>     T[] bar()
>     {
>         T[10] x;
>         return foo(x);
>     }
> 
> Now we've got an escaping reference to bar's stack. This is not memory safe. But giving up slices is a heavy burden.
> 
> So it occurred to me that the same solution for closures can be used here. If the address is taken of a stack variable in a safe function, that variable is instead allocated on the heap. If a more advanced compiler could prove that the address does not escape, it could be put back on the stack.
> 
> The code will be a little slower, but it will be memory safe. This change wouldn't be done in trusted or unsafe functions.

	Cyclone has this neat notion that a pointer is associated to a
memory "region" (by default, there are 3 regions: the data segment,
the heap and the stack of the current function, but you can have
user-defined regions). In this case, the function "foo" would have
the type:

	@region (`R) T[] foo (@region (`R) T[] a)

where `R is an abstract region name meaning that the return value is in the same region as the argument. When compiling "bar", the compiler would then be able to see that it is returning a pointer to bar's stack region and refuse.

		Jerome
-- 
mailto:jeberger@free.fr
http://jeberger.free.fr
Jabber: jeberger@jabber.fr



November 12, 2009
dsimcha wrote:
> == Quote from Don (nospam@nospam.com)'s article
>> There are definitely functions which are dangerous if you pass them
>> invalid parameters. ie, "use at own risk" -- any function which uses
>> them needs to add its own tests. I think something which implies "you
>> should think before you use this function" is reasonable.
>> I don't care at all what the name is, however. @system would be OK.
> 
> Yeah, and sometimes the functions that are unsafe when passed invalid parameters
> aren't obvious.

Also, even safe functions cannot be guaranteed safe if they are passed garbage as arguments.
1 2
Next ›   Last »