Thread overview
union/toString: crash/segfault: What's happening here?
Jan 12, 2018
kdevel
Jan 12, 2018
Nicholas Wilson
Jan 12, 2018
Adam D. Ruppe
Jan 12, 2018
ag0aep6g
Jan 12, 2018
Adam D. Ruppe
Jan 12, 2018
kdevel
Jan 12, 2018
H. S. Teoh
Jan 12, 2018
H. S. Teoh
January 12, 2018
crash.d
```
import std.stdio;

union U {
   float f;
   int i;
   string toString ()
   {
      string s;
      return s;
   }
}

void main ()
{
   U u;
   writeln (u);
}
```

$ dmd crash.d
$ ./crash

std.exception.ErrnoException@/.../dmd2/linux/bin64/../../src/phobos/std/stdio.d(2776):  (Bad address)
----------------
??:? @safe int std.exception.errnoEnforce!(int, "/.../dmd2/linux/bin64/../../src/phobos/std/stdio.d", 2776uL).errnoEnforce(int, lazy immutable(char)[]) [0x43f20a]
??:? @safe void std.stdio.File.LockingTextWriter.put!(immutable(char)[]).put(immutable(char)[]) [0x4422a7]
??:? @safe void std.range.primitives.doPut!(std.stdio.File.LockingTextWriter, immutable(char)[]).doPut(ref std.stdio.File.LockingTextWriter, ref immutable(char)[]) [0x44224b]
??:? @safe void std.range.primitives.put!(std.stdio.File.LockingTextWriter, immutable(char)[]).put(ref std.stdio.File.LockingTextWriter, immutable(char)[]) [0x44222b]
??:? void std.format.formatObject!(std.stdio.File.LockingTextWriter, crash.U, char).formatObject(ref std.stdio.File.LockingTextWriter, ref crash.U, ref const(std.format.FormatSpec!(char).FormatSpec)) [0x44220a]
??:? void std.format.formatValue!(std.stdio.File.LockingTextWriter, crash.U, char).formatValue(ref std.stdio.File.LockingTextWriter, ref crash.U, ref const(std.format.FormatSpec!(char).FormatSpec)) [0x44219d]
??:? uint std.format.formattedWrite!(std.stdio.File.LockingTextWriter, char, crash.U).formattedWrite(ref std.stdio.File.LockingTextWriter, const(char[]), crash.U) [0x43e703]
??:? void std.stdio.File.write!(crash.U, char).write(crash.U, char) [0x43e3f5]
??:? void std.stdio.writeln!(crash.U).writeln(crash.U) [0x43e389]
??:? _Dmain [0x43e344]


January 12, 2018
On Friday, 12 January 2018 at 00:54:03 UTC, kdevel wrote:
> crash.d
> ```
> import std.stdio;
>
> union U {
>    float f;
>    int i;
>    string toString ()
>    {
>       string s;
>       return s;
>    }
> }
>
> void main ()
> {
>    U u;
>    writeln (u);
> }
> ```
>
> $ dmd crash.d
> $ ./crash
>

because you don't initialise `s` in

>    string toString ()
>    {
>       string s;
>       return s;
>    }

so it defaults to `string s = null;` thus giving a segfault.

try `string s = "";` instead.
January 12, 2018
On Friday, 12 January 2018 at 01:45:37 UTC, Nicholas Wilson wrote:
> so it defaults to `string s = null;` thus giving a segfault.

null and "" are basically the same for strings. that's not the problem.
January 12, 2018
On 01/12/2018 02:45 AM, Nicholas Wilson wrote:
> because you don't initialise `s` in
> 
>>    string toString ()
>>    {
>>       string s;
>>       return s;
>>    }
> 
> so it defaults to `string s = null;` thus giving a segfault.
> 
> try `string s = "";` instead.

A null string is a perfectly fine empty string. Printing it does not lead to a segfault. And the thrown error is not a segfault.

Actually, the problem seems to be that s is not default initialized. It's garbage. And garbage usually isn't a proper string, so writeln fails. Looks like a compiler bug.
January 12, 2018
On Friday, 12 January 2018 at 00:54:03 UTC, kdevel wrote:
> $ dmd crash.d
> $ ./crash

Nicholas Wilson is right that you can use = "" to work around it, but with strings, null is supposed to behave the same way.

And this gives different (each wrong) behavior on -m32 vs -m64, which leads me to believe you actually found a compiler bug.

Calling u.toString directly also leads to random spam, which means it isn't even the library.

I'd file this as a compiler codegen bug.
January 12, 2018
Thanks for the quick answer!

On Friday, 12 January 2018 at 02:16:39 UTC, Adam D. Ruppe wrote:
> On Friday, 12 January 2018 at 00:54:03 UTC, kdevel wrote:
>> $ dmd crash.d
>> $ ./crash
>
> Nicholas Wilson is right that you can use = "" to work around it, but with strings, null is supposed to behave the same way.
>
> And this gives different (each wrong) behavior on -m32 vs -m64, which leads me to believe you actually found a compiler bug.

dmd -O crash even produces a binary which segfaults on my machine.

> Calling u.toString directly also leads to random spam, which means it isn't even the library.
>
> I'd file this as a compiler codegen bug.

https://issues.dlang.org/show_bug.cgi?id=18232
January 12, 2018
On Fri, Jan 12, 2018 at 11:09:47AM +0000, kdevel via Digitalmars-d-learn wrote: [...]
> On Friday, 12 January 2018 at 02:16:39 UTC, Adam D. Ruppe wrote:
[...]
> > I'd file this as a compiler codegen bug.
> 
> https://issues.dlang.org/show_bug.cgi?id=18232

Yep, definitely a codegen bug.  Apparently, local variables in union member functions aren't initialized to .init as they should be.  Digging into the compiler code right now to see if I can find where the problem is...


T

-- 
Only boring people get bored. -- JM
January 12, 2018
On Fri, Jan 12, 2018 at 10:49:45AM -0800, H. S. Teoh via Digitalmars-d-learn wrote:
> On Fri, Jan 12, 2018 at 11:09:47AM +0000, kdevel via Digitalmars-d-learn wrote: [...]
[...]
> > https://issues.dlang.org/show_bug.cgi?id=18232
> 
> Yep, definitely a codegen bug.  Apparently, local variables in union member functions aren't initialized to .init as they should be.
[...]

Fix: https://github.com/dlang/dmd/pull/7687

Temporary workaround: explicitly initialize your local variables in union member functions.


T

-- 
Life begins when you can spend your spare time programming instead of watching television. -- Cal Keegan