Memory safe in D

bachmeier no at spam.net
Mon Mar 11 20:39:59 UTC 2024


On Monday, 11 March 2024 at 19:22:54 UTC, Richard (Rikki) Andrew 
Cattermole wrote:
> On 12/03/2024 4:31 AM, bachmeier wrote:
>> On Monday, 11 March 2024 at 08:48:47 UTC, Richard (Rikki) 
>> Andrew Cattermole wrote:
>>> On 11/03/2024 9:16 PM, Alex wrote:
>>>> So I don't see any errors or warnings from compiler when I 
>>>> use uninitialized variable |a| and don't see any exception 
>>>> with backtrace in runtime (application is build in debug 
>>>> mode).
>>>>
>>>> Is it expected behavior? Looks like it is not very safe 
>>>> approach and can lead to very unpleasant memory errors...
>>>
>>> This is expected behavior.
>>>
>>> The variable a was default initialized to null.
>>>
>>> D has not got type state analysis as part of it, so it cannot 
>>> detect this situation and cause an error.
>>>
>>> It is at the top of my todo list for memory safety research 
>>> for D, as the IR it requires enables other analysis and 
>>> provides a framework for it to exist in.
>> 
>> Rather than doing that, couldn't the compiler say `A a;` is 
>> not valid inside `@safe`?
>
> One of the improvements for type state analysis I want to make 
> is for methods:
>
> ```d
> class Foo {
> 	void func(this'nonnull);
> }
> ```
>
> Instead of:
>
> ```d
> class Foo {
> 	void func(this'reachable);
> }
> ```
>
> That'll catch it when you try to call something.
>
> However I'm not sure if disallowing null entering is a great 
> idea, its going to enter through other methods so you might as 
> well embrace catching that as well.

What I've never understood is the valid use case for `A a;` that 
would justify that line compiling. I don't do much with classes, 
but the same thing comes about with structs. Why would it make 
sense to write code like this, particularly if you've marked it 
@safe?

```
struct Foo {
   double n;
   string s = string.init;
}

Foo * f;
// Crashes
writeln(f.n);

Foo * f = void;
// Doesn't crash but gives wrong output
writeln(f.n);

Foo * g;
// Crashes
g.n = 3.3;

Foo * g = void;
g.n = 3.3;
// Correct output
writeln(g.n);
// Crashes
writeln(g.s);
```


More information about the Digitalmars-d mailing list