On Fri, 13 Nov 2009 08:45:28 -0500, Denis Koroskin <2kor...@gmail.com> wrote:

On Fri, 13 Nov 2009 16:16:29 +0300, Steven Schveighoffer <schvei...@yahoo.com> wrote:

On Fri, 13 Nov 2009 07:46:02 -0500, Denis Koroskin <2kor...@gmail.com> wrote:


Sure (with the current compiler):

char[] foo()
{
   char buf[100];
   // fill buf
   return strstr(buf, "hi"); // no .dup, buf escapes
}


No, no, no! It's foo which is unsafe in your example, not strstr!

OK, tell me if foo is now safe or unsafe:

@safe char[] bar(char[] x);

char[] foo()
{
   char buf[100];
   return bar(buf);
}


It is unsafe even if bar doesn't return anything (it could store reference to a buf in some global variable, for example). Or accessing globals is considered unsafe now?

No, it's *potentially* unsafe.  If bar is written like this:

@safe char[] bar(char[] x){ return x.dup;}

Then bar is completely safe in all contexts, and therefore foo is completely safe. Merely taking the address of a stack variable does not make a function unsafe.

Is this unsafe?

char[] foo()
{
  char buf[100];
  return buf[0..50].dup;
}

What about this?

void foo(int a, int b)
{
swap(a, b); // uses references to local variables, what if swap stores a reference to one of its args in a global?
}

You might understand that if these kinds of thing is not allowed to be marked as safe, you might have non-stop complaints from new users and critics of D about how D's "safety" features are a joke, just like Vista's security popups are a joke. And then everything gets marked as @trusted or unmarked, and safed becomes a complete waste of time. We need to choose rules that are good for safety, but which allow intuitive code to be written.

It is foo's fault that pointer to a stack allocated buffer is passed and returned outside of the scope. The dangerous line is buf[], which gets a slice out of a static array, not return bar(...). You could as well write:

char[] foo()
{
     char buf[100];
     return buf[]; // no more bar, but code is still dangerous
}

The line is most of the time fuzzy whose fault it is. This is why definitions of what is allowed and what is not are important. Your example looks obvious, but there is code that does not look so obvious. Unless you know exactly the flow of the data in the functions you call, then you can't prove whether it's safe or not. I hope that someday the compiler can prove safety even through function calls, but we are a long ways away from that.

-Steve

Reply via email to