Can we just have struct inheritence already?

Timon Gehr timon.gehr at gmx.ch
Thu Jun 13 21:18:16 UTC 2019


On 13.06.19 22:55, Exil wrote:
> On Thursday, 13 June 2019 at 19:21:53 UTC, Tim wrote:
>> On Tuesday, 11 June 2019 at 00:30:27 UTC, Walter Bright wrote:
>>> If you want @safe to mean "no undefined behavior", that is a valid 
>>> opinion, but that is not what @safe in D is currently defined as. It 
>>> is currently defined as "memory safe". If you can find a case where 
>>> an int with garbage in it can cause memory corruption in @safe code, 
>>> that would indeed be a bug in D.
>>
>> The following code causes memory corruption, because a bool has 
>> garbage in it.
>>
>> import std.stdio;
>>
>> // Returns newly allocated data with increased value if b is true.
>> // Returns same data otherwise.
>> const(int)* test(immutable int *data, bool b) @trusted
>> {
>>     int *data2;
>>     if(!b)
>>     {
>>         writeln("b seems to be false");
>>         // The cast can be trusted, because data2 will only be 
>> modified if b is true.
>>         data2 = cast(int*)data;
>>     }
>>     else
>>     {
>>         writeln("b seems to be true");
>>         data2 = new int(*data);
>>     }
>>
>>     if(b)
>>     {
>>         writeln("b seems to be true");
>>         *data2 += 1;
>>     }
>>     return data2;
>> }
>>
>> void main() @safe
>> {
>>     bool b = void;
>>     immutable int *data = new immutable int(1);
>>     writeln("data before: ", *data);
>>     const int *data2 = test(data, b);
>>     writeln("data after: ", *data);
>>     writeln("data2 after: ", *data2);
>> }
>>
>> After compiling it with dmd and running it I get the following output:
>> data before: 1
>> b seems to be false
>> b seems to be true
>> data after: 2
>> data2 after: 2
>>
>> The immutable integer pointed to by data is modified. The function 
>> test is @trusted, but only modifies the immutable data, because b 
>> seems to be true and false at the same time.
>> Normally a bool is internally 0 or 1 and the compiler can assume that. 
>> If b has another value and !b is implemented as ~b, then b and !b can 
>> both be true.
>>
>> This means, that uninitialized data can result in memory corruption.
> 
> This problem happens because you are used @trusted. If you used @safe 
> you wouldn't be able to increment pointers and modify the values the way 
> you did in @trusted.

What that code illustrates is that `void` initialization leads to 
boolean values that are both `true` and `false` at the same time.

The @trusted function in the example can't do anything bad assuming that 
`b` is either true or false. If `void` initialization is @safe, @trusted 
functions can no longer assume that boolean parameters cannot be `true` 
and `false` at the same time. What's more, neither can @safe functions.

In my book, an optimizer that can't elide the `if(b)` in the above code 
is a bad optimizer. Therefore either `void` initialization should not be 
@safe, or `void` initialization of a bool should be guaranteed to result 
in a value that is either true or false, but not both.


More information about the Digitalmars-d mailing list