Jump to page: 1 2
Thread overview
@safe - why does this compile?
Jul 13, 2018
Piotr Mitana
Jul 13, 2018
ketmar
Jul 13, 2018
ketmar
Jul 16, 2018
Johan Engelen
Jul 16, 2018
ketmar
Jul 16, 2018
ketmar
Jul 13, 2018
bauss
Jul 13, 2018
Timoses
Jul 13, 2018
Dukc
Jul 14, 2018
Timoses
July 13, 2018
This code:

    import std.stdio;

    class X1 {}
    class X2 : X1
    {
	void run() @safe
        {
            writeln("DONE");
        }
    }

    void main() @safe
    {
        X1 x1 = new X1;
        X2 x2 = cast(X2) x1;
        x2.run();
    }

is obviously wrong gets killed by OS's signal. Why is it @safe? I thought @safe should prevent such errors as well.
July 13, 2018
Piotr Mitana wrote:

> This code:
>
>      import std.stdio;
>
>      class X1 {}
>      class X2 : X1
>      {
> 	void run() @safe
>          {
>              writeln("DONE");
>          }
>      }
>
>      void main() @safe
>      {
>          X1 x1 = new X1;
>          X2 x2 = cast(X2) x1;
>          x2.run();
>      }
>
> is obviously wrong gets killed by OS's signal. Why is it @safe? I thought @safe should prevent such errors as well.

there is nothing wrong here. dereferencing null reference is completely safe (in terms of result predictability).
July 13, 2018
On Friday, 13 July 2018 at 11:04:40 UTC, Piotr Mitana wrote:
> This code:
>
>     import std.stdio;
>
>     class X1 {}
>     class X2 : X1
>     {
> 	void run() @safe
>         {
>             writeln("DONE");
>         }
>     }
>
>     void main() @safe
>     {
>         X1 x1 = new X1;
>         X2 x2 = cast(X2) x1;
>         x2.run();
>     }
>
> is obviously wrong gets killed by OS's signal. Why is it @safe? I thought @safe should prevent such errors as well.

See: https://dlang.org/spec/function.html#function-safety
July 13, 2018
On Friday, 13 July 2018 at 11:04:40 UTC, Piotr Mitana wrote:
> This code:
>
>     import std.stdio;
>
>     class X1 {}
>     class X2 : X1
>     {
> 	void run() @safe
>         {
>             writeln("DONE");
>         }
>     }
>
>     void main() @safe
>     {
>         X1 x1 = new X1;
>         X2 x2 = cast(X2) x1;
>         x2.run();
>     }
>
> is obviously wrong gets killed by OS's signal. Why is it @safe? I thought @safe should prevent such errors as well.

I suppose this is another good example of how casting can be dangerous?

E.g. also:

    immutable int i = 3;
    int* j = cast(int*)&i;
    assert(i == 3);
	*j = 4;
    assert(j == &i); // data occupies same address space
    assert(i == 3 && *j == 4); // yet the values differ
July 13, 2018
On 7/13/18 7:22 AM, ketmar wrote:
> Piotr Mitana wrote:
> 
>> This code:
>>
>>      import std.stdio;
>>
>>      class X1 {}
>>      class X2 : X1
>>      {
>>     void run() @safe
>>          {
>>              writeln("DONE");
>>          }
>>      }
>>
>>      void main() @safe
>>      {
>>          X1 x1 = new X1;
>>          X2 x2 = cast(X2) x1;
>>          x2.run();
>>      }
>>
>> is obviously wrong gets killed by OS's signal. Why is it @safe? I thought @safe should prevent such errors as well.
> 
> there is nothing wrong here. dereferencing null reference is completely safe (in terms of result predictability).

To emphasize the point, this is @safe as well:

X2 x2; // = null
x2.run();

D does not consider a segmentation fault due to null dereferencing to be unsafe -- no memory corruption happens.

-Steve
July 13, 2018
Steven Schveighoffer wrote:

> To emphasize the point, this is @safe as well:
>
> X2 x2; // = null
> x2.run();
>
> D does not consider a segmentation fault due to null dereferencing to be unsafe -- no memory corruption happens.

yeah. in simple words: safe code is *predictable*, but not "segfault-less". segfaults (null dereferences) in safe code are allowed, 'cause they have completely predictable behavior (instant program termination).

@safe doesn't free you from doing your null checks, it protects you from so-called "undefined behavior" (aka "unpredictable execution results"). so when we are talking about "memory safety", it doesn't mean that your code cannot segfault, it means that your code won't corrupt random memory due to misbehaving.
July 13, 2018
On Friday, 13 July 2018 at 13:52:27 UTC, Timoses wrote:
> I suppose this is another good example of how casting can be dangerous?
>
> E.g. also:
>
>     immutable int i = 3;
>     int* j = cast(int*)&i;
>     assert(i == 3);
> 	*j = 4;
>     assert(j == &i); // data occupies same address space
>     assert(i == 3 && *j == 4); // yet the values differ

No, casting classes to their subclasses is not dangerous to program integrity, because it is checked. It is just a regular bug that terminates the program when encountered.

But casting away immutable can break program integrity as your example demonstrates. For that reason the compiler won't let you do that if you wrap that code in @safe, unlike the class cast.
July 14, 2018
On Friday, 13 July 2018 at 22:17:59 UTC, Dukc wrote:
> On Friday, 13 July 2018 at 13:52:27 UTC, Timoses wrote:
>> I suppose this is another good example of how casting can be dangerous?
>>
>> E.g. also:
>>
>>     immutable int i = 3;
>>     int* j = cast(int*)&i;
>>     assert(i == 3);
>> 	*j = 4;
>>     assert(j == &i); // data occupies same address space
>>     assert(i == 3 && *j == 4); // yet the values differ
>
> No, casting classes to their subclasses is not dangerous to program integrity, because it is checked. It is just a regular bug that terminates the program when encountered.
>
> But casting away immutable can break program integrity as your example demonstrates. For that reason the compiler won't let you do that if you wrap that code in @safe, unlike the class cast.

Thanks for the explanation. Only read the function safety chapter in depth after posting this : D.

Still, is `cast`ing seen as something "dangerous" or as something that should only be done as a last resort? Should std.conv : to be prioritized?
July 14, 2018
On 7/14/18 2:50 AM, Timoses wrote:
> On Friday, 13 July 2018 at 22:17:59 UTC, Dukc wrote:
>> On Friday, 13 July 2018 at 13:52:27 UTC, Timoses wrote:
>>> I suppose this is another good example of how casting can be dangerous?
>>>
>>> E.g. also:
>>>
>>>     immutable int i = 3;
>>>     int* j = cast(int*)&i;
>>>     assert(i == 3);
>>>     *j = 4;
>>>     assert(j == &i); // data occupies same address space
>>>     assert(i == 3 && *j == 4); // yet the values differ
>>
>> No, casting classes to their subclasses is not dangerous to program integrity, because it is checked. It is just a regular bug that terminates the program when encountered.
>>
>> But casting away immutable can break program integrity as your example demonstrates. For that reason the compiler won't let you do that if you wrap that code in @safe, unlike the class cast.
> 
> Thanks for the explanation. Only read the function safety chapter in depth after posting this : D.
> 
> Still, is `cast`ing seen as something "dangerous" or as something that should only be done as a last resort? Should std.conv : to be prioritized?

Well, std.conv.to is going to throw if it doesn't dynamically convert. So it depends on the behavior you want. But yeah, if you know it's going to work, you probably want to do std.conv.to, it's safer.

Just FYI, it's kind of bad that you have to use cast here, because cast isn't going to distinguish between dynamic casting and const casting. It's kind of a problem in D in general. We don't have C++ niceties like const_cast etc.

-Steve
July 16, 2018
On Friday, 13 July 2018 at 14:51:17 UTC, ketmar wrote:
>
> yeah. in simple words: safe code is *predictable*, but not "segfault-less". segfaults (null dereferences) in safe code are allowed, 'cause they have completely predictable behavior (instant program termination).
>
> @safe doesn't free you from doing your null checks, it protects you from so-called "undefined behavior" (aka "unpredictable execution results"). so when we are talking about "memory safety", it doesn't mean that your code cannot segfault, it means that your code won't corrupt random memory due to misbehaving.

This is not true when using LDC (and I'd expect the same for GDC).
With LDC, dereferencing `null` is undefined behavior regardless of whether you are in an @safe context or not.

- Johan

« First   ‹ Prev
1 2