January 23, 2018
On Tuesday, 23 January 2018 at 02:25:57 UTC, Mike Franklin wrote:

> Should `destroy` be `@system` so it can't be called in `@safe` code, or should the compiler be smart enough to figure out the flow control and throw an error?

Interestingly, `destroy` is an unsafe operation for classes.

import std.stdio;

class A
{
    void hello() @safe { writeln("hello"); }
}

void main() @safe
{
    A a = new A();
    a.hello();
    destroy(a);  // onlineapp.d(12): Error: @safe function 'D main' cannot call
                 // @system function 'object.destroy!(A).destroy'
    a.hello();
}

https://run.dlang.io/is/AwKBc3


But it's not an unsafe operation for structs

import std.stdio;

struct A
{
    int i;
    void print() @safe { writeln(i); }
}

void main() @safe
{
    A* a = new A();
    a.print();  // OK
    a.destroy();
    a.print();  // Error!
}

https://run.dlang.io/is/Fm7qBR

Not sure if that's a bug or not.

Mike
January 23, 2018
On 01/23/2018 03:38 AM, Mike Franklin wrote:
> import std.stdio;
> 
> void main() @safe
> {
>      string foo = "foo";
>      string* ls0;
>      string* p1, p2;
> 
>      ls0 = &foo;
>      p1 = ls0;
>      ls0.destroy();
>      p2 = ls0;
>      writeln(p2.length);
> }
> 
> Compile with `-dip1000`
> 
> Error: program killed by signal 11
> 
> https://run.dlang.io/is/6L6zcH
> 
> So that's bad.  But it looks like a bug in `-dip1000`, because if I compile without `-dip1000`, I get:
> 
> onlineapp.d(9): Error: cannot take address of local foo in @safe function main
> 
> https://run.dlang.io/is/rHpuf1

No bug.

`&foo` never leaves the scope, so `-dip1000` correctly allows it. If you try to `return p1;` or `return p2;`, you get errors from `-dip1000`.

Other than that, `ls0.destroy();` just does `ls0 = null;` and then the `writeln` does a null dereference which is considered to be a guaranteed segfault. Segfaults are considered safe and `@safe` is not supposed to prevent them.
January 23, 2018
On Monday, 22 January 2018 at 23:30:16 UTC, Aedt wrote:
> I was asked in Reddit (https://www.reddit.com/r/learnprogramming/comments/7ru82l/i_was_thinking_of_using_d_haxe_or_another/) how would D handle the following similar D code. I'm surprised that both dmd and ldc provides no warnings even with -w argument passed.

Well, if you want to check much at compile time, you probably want SPARK or F* (fstar).
January 23, 2018
On 1/22/18 11:11 PM, Mike Franklin wrote:
> On Tuesday, 23 January 2018 at 02:25:57 UTC, Mike Franklin wrote:
> 
>> Should `destroy` be `@system` so it can't be called in `@safe` code, or should the compiler be smart enough to figure out the flow control and throw an error?
> 
> Interestingly, `destroy` is an unsafe operation for classes.

Because it's calling a @system function, rt_finalize. This function calls whatever is in the destructor, and because it works on Object level, it has no idea what the actual attributes of the derived destructor are.

This needs to be fixed, but a whole host of issues like this exist with Object.

> But it's not an unsafe operation for structs

Because struct destructors are not virtual. The compiler can tell when a struct destructor is unsafe:

https://run.dlang.io/is/o3ujrP

Note, I had to call destroy in a sub-function because if I made main @safe, it would fail to compile due to automatic destruction.

> 
> Not sure if that's a bug or not.

Not a bug.

Also, as others have pointed out, null dereferences are also considered @safe [1]. destroying an object doesn't actually deallocate it. It puts it into a state that is @safe to call, but will likely crash.

On 1/22/18 9:43 PM, Nicholas Wilson wrote:
>
> The compiler should be taught that any access to a `.destroy()`ed object
> is invalid i.e. that its lifetime ends when destroy is called.

destroy is just a function, there shouldn't be any special magic for it (we have enough of that already). And in fact its lifetime has not ended, it's just destructed, and left as an empty shell.

The idea behind destroy is to decouple destruction from deallocation (as delete combines the two). @safe is all about memory safety, nothing else. As long as you can't corrupt memory, it is @safe.

-Steve

[1] Note: the reason they are safe is because they generally result in a segfault, which doesn't harm any memory. This is very much a user-space POV, and doesn't take into account kernel-space where null dereferences may actually be valid memory! It also doesn't (currently) take into account possible huge objects that could extend into valid memory space, even in user space.
January 24, 2018
On Tuesday, 23 January 2018 at 21:53:24 UTC, Steven Schveighoffer wrote:

>> Interestingly, `destroy` is an unsafe operation for classes.
>
> Because it's calling a @system function, rt_finalize. This function calls whatever is in the destructor, and because it works on Object level, it has no idea what the actual attributes of the derived destructor are.
>
> This needs to be fixed, but a whole host of issues like this exist with Object.

Are there any bugzilla issues that you are aware of that document this?

Mike
January 24, 2018
On Tuesday, 23 January 2018 at 21:53:24 UTC, Steven Schveighoffer wrote:

> [1] Note: the reason they are safe is because they generally result in a segfault, which doesn't harm any memory. This is very much a user-space POV, and doesn't take into account kernel-space where null dereferences may actually be valid memory! It also doesn't (currently) take into account possible huge objects that could extend into valid memory space, even in user space.

That's what kindof ticks me off about this "null is memory safe" argument; it seems to be only applicable to a specific platform and environment.  I have a micocontroller in front of me where an address of null (essentially 0) is a perfectly valid memory address.

Mike
January 23, 2018
On 1/23/2018 4:42 PM, Mike Franklin wrote:
> That's what kindof ticks me off about this "null is memory safe" argument; it seems to be only applicable to a specific platform and environment.

It's an extremely useful argument, though, as modern computers have virtual memory systems that map 0 to a seg fault, and have since the 80's, specifically because it DOES catch lots and lots of bugs.

I always thought the IBM PC should have put the ROMs at address 0 instead of FFFF0. It probably would have saved billions of dollars.


> I have a micocontroller in front of me where an address of null (essentially 0) is a perfectly valid memory address.

Microcontroller code tends to be small and so it's unlikely that you'll need to worry about it.

January 24, 2018
On Wednesday, 24 January 2018 at 01:44:51 UTC, Walter Bright wrote:

> Microcontroller code tends to be small and so it's unlikely that you'll need to worry about it.

I think you need to get involved in programming microcontrollers again because the landscape has changed drastically.  The microcontrollers I use now are more powerful than PCs of the 90's.

The project I'm currently working on is an HMI for industrial control with a full touchscreen 2D GUI.  The code base  is 240,084 lines of code and that doesn't even include the 3rd party libraries I'm using (e.g. 2D graphics library, newlib C library, FreeType font rendering library).  That's not "small" by my standard of measure.

And with devices such as this being increasingly connected to the Internet, such carelessness can easily be exploited as evident in https://en.wikipedia.org/wiki/2016_Dyn_cyberattack   And that's not to mention the types of critical systems that run on such platforms that we are increasingly becoming more dependent on.

We better start worrying about it.

Mike
January 23, 2018
On Wednesday, January 24, 2018 02:28:12 Mike Franklin via Digitalmars-d wrote:
> On Wednesday, 24 January 2018 at 01:44:51 UTC, Walter Bright
>
> wrote:
> > Microcontroller code tends to be small and so it's unlikely that you'll need to worry about it.
>
> I think you need to get involved in programming microcontrollers again because the landscape has changed drastically.  The microcontrollers I use now are more powerful than PCs of the 90's.
>
> The project I'm currently working on is an HMI for industrial control with a full touchscreen 2D GUI.  The code base  is 240,084 lines of code and that doesn't even include the 3rd party libraries I'm using (e.g. 2D graphics library, newlib C library, FreeType font rendering library).  That's not "small" by my standard of measure.
>
> And with devices such as this being increasingly connected to the Internet, such carelessness can easily be exploited as evident in https://en.wikipedia.org/wiki/2016_Dyn_cyberattack   And that's not to mention the types of critical systems that run on such platforms that we are increasingly becoming more dependent on.
>
> We better start worrying about it.

Well, we can just mandate that dereferencing null be @safe such that if it's not guaranteed that dereferencing null will segfault, the compiler will have to insert additional checks. We need to do that anyway for the overly large objects (and unfortunately don't last I heard). But as long as null checks aren't inserted when the target is going to segfault on dereferencing null, then we're not inserting unnecessary checks. That way, stuff running on a normal CPU would be the same as now (save for the objects that are too large for segfaulting to work), and targets like a microcontroller would get the extra checks so that they behaved more like if they were going to segfault on dereferencing null.

But making dereferencing null @system makes no sense, because that would mean that dereferencing pointers and references in general could not be @safe. So, basically, anything that's not on the stack would then be @system. And that would destroy @safe.

- Jonathan M Davis

January 24, 2018
On Wednesday, 24 January 2018 at 02:28:12 UTC, Mike Franklin wrote:
> On Wednesday, 24 January 2018 at 01:44:51 UTC, Walter Bright wrote:
>
>> Microcontroller code tends to be small and so it's unlikely that you'll need to worry about it.
>
> I think you need to get involved in programming microcontrollers again because the landscape has changed drastically.  The microcontrollers I use now are more powerful than PCs of the 90's.
>
> The project I'm currently working on is an HMI for industrial control with a full touchscreen 2D GUI.  The code base  is 240,084 lines of code and that doesn't even include the 3rd party libraries I'm using (e.g. 2D graphics library, newlib C library, FreeType font rendering library).  That's not "small" by my standard of measure.
>
> And with devices such as this being increasingly connected to the Internet, such carelessness can easily be exploited as evident in https://en.wikipedia.org/wiki/2016_Dyn_cyberattack   And that's not to mention the types of critical systems that run on such platforms that we are increasingly becoming more dependent on.
>
> We better start worrying about it.
>
> Mike

Well if your embedded device has all that on it you should be sitting on an OS with proper memory management support. Even the hokey FreeRTOS can be configured to throw a hardware exception on nullptr access.

I work on critical systems SW developing life support and pace makers. For us nullptrs and memory management is not an issue. It is not hard to design these problems out of the critical component architecture.

The bigger problem is code logic bugs and for that we make heavy use of asserts and in-out contracts. We don't use D, it is all C++ and some Ada in the older systems.

bye,
lobo