Bug 19631 – Segfault on simple nested templated struct
Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2019-01-29T15:51:07Z
Last change time
2020-03-21T03:56:39Z
Assigned to
No Owner
Creator
Arne Marschall
Comments
Comment #0 by bestellung — 2019-01-29T15:51:07Z
The code below causes DMD to segfault. (while gdc works fine)
I have tried different configurations (debug / release and more), but there
All tried with Ubuntu 18.04 64bit
import std.stdio;
/*
dmd fails with exit code 139 on this.
dmd --version
DMD64 D Compiler v2.084.0
(gdc (Ubuntu 8.2.0-1ubuntu2~18.04) 8.2.0) builds and runs correct)
*/
struct Field(int _w, int _h)
{
bool[_h][_w] s;
}
struct Life(int w, int h)
{
//Two versions below both crash it
//auto a = new Field!(w, h);
Field!(w, h)* a = new Field!(w, h);
//This would work - the nesting seems to trigger it
//bool[h][w] a;
}
void main()
{
Life!(100, 100) f1;
//auto f2 = new Life!(128,128);
}
Comment #1 by b2.temp — 2019-01-29T17:22:23Z
regressed since 2.070.0 (or one of its patch release)
Comment #2 by b2.temp — 2019-01-29T18:06:03Z
Problem happens when the initializer type is being determined.
In case of this issue is blocking some work there are two possible workarounds in addition to the "non nesting" solution.
1. Field!(w, h) a = *new Field!(w, h);
2. bool[_h][_w] s = void;
bt:
---
Program received signal SIGSEGV, Segmentation fault.
0x00000000006466a0 in Type::isImmutable() const (this=0x0) at dmd/mtype.d:1072
1072 return (mod & MODFlags.immutable_) != 0;
Missing separate debuginfos, use: dnf debuginfo-install libgcc-8.2.1-6.fc28.x86_64
(gdb) bt
#0 0x00000000006466a0 in Type::isImmutable() const (this=0x0) at dmd/mtype.d:1072
#1 0x0000000000646929 in Type::immutableOf() (this=0x0) at dmd/mtype.d:1167
#2 0x00000000006454ae in Type::equivalent(Type*) (this=0x7ffff6aac6c0, t=0x0) at dmd/mtype.d:534
#3 0x00000000006b538e in _D3dmd4todt8toDtElemFCQu5mtype10TypeSArrayKSQBq7backend2dt9DtBuilderCQCp10expression10ExpressionZv (e=0x7ffff6aad4c0, dtb=...,
tsa=0x7ffff6aac5f0) at dmd/todt.d:868
#4 0x00000000006b508e in _D3dmd4todt11membersToDtFCQy9aggregate20AggregateDeclarationKSQCi7backend2dt9DtBuilderPSQDi4root5array__T5ArrayTCQEh10expression10ExpressionZQBkmCQFo6dclass16ClassDeclarationPPPSQGuQBg9BaseClassZv (ppb=0x0, concreteType=0x0, firstFieldIndex=0, elements=0x7ffff6aad580, dtb=...,
ad=0x7ffff6aab7f0) at dmd/todt.d:792
#5 0x00000000006b43c9 in Expression_toDt::ExpToDt::visit(StructLiteralExp*) (this=0x7fffffffcd18, sle=0x7ffff6aad5a0) at dmd/todt.d:469
#6 0x00000000005d358e in StructLiteralExp::accept(Visitor*) (this=0x7ffff6aad5a0, v=0x7fffffffcd18) at dmd/expression.d:3103
#7 0x00000000006b3913 in Expression_toDt(Expression*, DtBuilder&) (e=0x7ffff6aad5a0, dtb=...) at dmd/todt.d:585
#8 0x00000000006b87ae in toSymbol(StructLiteralExp*) (sle=0x7ffff6aad5a0) at dmd/tocsym.d:677
#9 0x00000000006b3ae2 in Expression_toDt::ExpToDt::visit(AddrExp*) (this=0x7fffffffce18, e=0xba5750) at dmd/todt.d:271
#10 0x00000000005d790e in AddrExp::accept(Visitor*) (this=0xba5750, v=0x7fffffffce18) at dmd/expression.d:4892
#11 0x00000000006b3913 in Expression_toDt(Expression*, DtBuilder&) (e=0xba5750, dtb=...) at dmd/todt.d:585
#12 0x00000000006b38c6 in _D3dmd4todt16Initializer_toDtRCQBd4init11InitializerKSQCa7backend2dt9DtBuilderZ8visitExpMFCQDlQCi14ExpInitializerZv (
__capture=0x7fffffffcea0, ei=0x7ffff6aaa6a0) at dmd/todt.d:197
---Type <return> to continue, or q <return> to quit---
#13 0x00000000006b321c in Initializer_toDt(Initializer*, DtBuilder&) (init=0x7ffff6aaa6a0, dtb=...) at dmd/todt.d:206
#14 0x00000000006b5148 in _D3dmd4todt11membersToDtFCQy9aggregate20AggregateDeclarationKSQCi7backend2dt9DtBuilderPSQDi4root5array__T5ArrayTCQEh10expression10ExpressionZQBkmCQFo6dclass16ClassDeclarationPPPSQGuQBg9BaseClassZv (ppb=0x0, concreteType=0x0, firstFieldIndex=0, elements=0x0, dtb=..., ad=0x7ffff6aa9e00)
at dmd/todt.d:811
#15 0x00000000006b48d7 in StructDeclaration_toDt(StructDeclaration*, DtBuilder&) (sd=0x7ffff6aa9e00, dtb=...) at dmd/todt.d:604
#16 0x00000000006c01f0 in toObjFile::ToObjFile::visit(StructDeclaration*) (this=0x7fffffffd1b8, sd=0x7ffff6aa9e00) at dmd/toobj.d:512
#17 0x000000000059d64a in StructDeclaration::accept(Visitor*) (this=0x7ffff6aa9e00, v=0x7fffffffd1b8) at dmd/dstruct.d:592
#18 0x00000000006c0d41 in _D3dmd5toobj9toObjFileRCQw7dsymbol7DsymbolbZ9ToObjFile5visitMRCQCj9dtemplate16TemplateInstanceZ__T9__lambda2TQDiZQpMFQDqZv (
__capture=0x7fffffffd160, s=0x7ffff6aa9e00) at dmd/toobj.d:836
#19 0x000000000059dbc4 in _D3dmd7dsymbol14foreachDsymbolFPSQBf4root5array__T5ArrayTCQCeQCd7DsymbolZQxMDFQvZvZv (dg=..., symbols=0x7ffff6aa9de0)
at dmd/dsymbol.d:97
#20 0x00000000006c0d17 in toObjFile::ToObjFile::visit(TemplateInstance*) (this=0x7fffffffd1b8, ti=0x7ffff6d46fe0) at dmd/toobj.d:836
#21 0x00000000005c70de in TemplateInstance::accept(Visitor*) (this=0x7ffff6d46fe0, v=0x7fffffffd1b8) at dmd/dtemplate.d:7507
#22 0x00000000006bfa72 in toObjFile(Dsymbol*, bool) (ds=0x7ffff6d46fe0, multiobj=false) at dmd/toobj.d:1020
#23 0x00000000006b0664 in genObjFile(Module*, bool) (m=0x7ffff6d44d80, multiobj=false) at dmd/glue.d:409
#24 0x000000000063fb7c in _D3dmd4mars7tryMainFmPPxaKSQz7globals5ParamZi (params=..., argv=0x7fffffffddc8, argc=2) at dmd/mars.d:705
#25 0x0000000000640759 in D main () at dmd/mars.d:858
---
Comment #3 by bestellung — 2019-01-30T20:43:05Z
(In reply to Basile-z from comment #2)
> Problem happens when the initializer type is being determined.
> In case of this issue is blocking some work there are two possible
> workarounds in addition to the "non nesting" solution.
>
> 1. Field!(w, h) a = *new Field!(w, h);
> 2. bool[_h][_w] s = void;
Actually this is not a blocker, I am only training myself. So I ported this "Game of Life" example and experimented with different arrays. The templated version crashed it.
This would work as well
Field!(w, h) a;
But the complete code uses two instances of Field, a & b and swaps them a lot.
Swapping of a and b is done much faster if they are pointers instead of 100x100 arrays.
This version compiles as well and takes advantage of the internal pointers within dynamic arrays.
auto ab = [Field!(w, h).init, Field!(w, h).init];
instead of a and b it uses ab[0] and ab ab[1].
And swaps them here.
import std.algorithm.mutation : swap;
swap(ab[0], ab[1]);
Comment #4 by dlang-bot — 2019-05-20T02:46:45Z
dlang/dmd pull request #9821 "Fix issue 19631 - ICE on multi dim static array initializer" was merged into stable:
- 25062622de684c9f6671a2782a514d07c7c37381 by سليمان السهمي (Suleyman Sahmi):
Fix issue 19631 - ICE on multi dim static array initializer
https://github.com/dlang/dmd/pull/9821