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