@safe leak fix?
Steven Schveighoffer
schveiguy at yahoo.com
Fri Nov 13 06:05:55 PST 2009
On Fri, 13 Nov 2009 08:45:28 -0500, Denis Koroskin <2korden at gmail.com>
wrote:
> On Fri, 13 Nov 2009 16:16:29 +0300, Steven Schveighoffer
> <schveiguy at yahoo.com> wrote:
>
>> On Fri, 13 Nov 2009 07:46:02 -0500, Denis Koroskin <2korden at 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
More information about the Digitalmars-d
mailing list