Bug 6473 – Stack overflow with struct destructor as default parameter
Status
RESOLVED
Resolution
FIXED
Severity
major
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2011-08-11T19:08:00Z
Last change time
2012-02-01T04:03:49Z
Keywords
ice, patch
Assigned to
nobody
Creator
hoganmeier
Comments
Comment #0 by hoganmeier — 2011-08-11T19:08:12Z
struct Eins
{
~this() {}
}
struct Zwei
{
void build(Eins devices = Eins())
{
}
}
$ gdb --batch -ex "run program.d" -ex "bt 10" dmd
DMD v2.054 DEBUG
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff72e4893 in vfprintf () from /lib/x86_64-linux-gnu/libc.so.6
#0 0x00007ffff72e4893 in vfprintf () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007ffff730af02 in vsnprintf () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x00007ffff72efc4f in snprintf () from /lib/x86_64-linux-gnu/libc.so.6
#3 0x00000000004fa225 in Lexer::uniqueId (s=0x5b4aaa "__sl", num=8590) at lexer.c:2881
#4 0x00000000004fa277 in Lexer::uniqueId (s=0x5b4aaa "__sl") at lexer.c:2888
#5 0x00000000004a0204 in StructLiteralExp::semantic (this=0x1128b80, sc=0x1128a70) at expression.c:3648
#6 0x000000000047281d in VarDeclaration::semantic (this=0x1128890, sc=0x1128a70) at declaration.c:1280
#7 0x00000000004a4390 in DeclarationExp::semantic (this=0x1128990, sc=0x1128670) at expression.c:4910
#8 0x00000000004a66f5 in BinExp::semantic (this=0x1128a20, sc=0x1128670) at expression.c:5626
#9 0x00000000004a6881 in BinExp::semanticp (this=0x1128a20, sc=0x1128670) at expression.c:5646
build as a free function doesn't trigger it.
Nor does a global 'Eins devices = Eins();'.
btw, lexer.c(2876):
Identifier *Lexer::uniqueId(const char *s, int num)
{ char buffer[32];
size_t slen = strlen(s);
assert(slen + sizeof(num) * 3 + 1 <= sizeof(buffer));
sprintf(buffer, "%s%d", s, num);
Why that sizeof(num) there? It's always 4.
Why isn't snprintf(buffer, 32.... used?
Comment #1 by clugdbug — 2011-09-19T02:10:40Z
It's not a segfault, and it has nothing to do with Lexer::uniqueId.
It's a stack overflow. It's also D2-only, because it requires a struct destructor.
StructLiteralExp::semantic() sees that Eins has a destructor, so it rewrites it as
Eins devices = (Eins tmp = Eins(), tmp);
Then, it runs semantic on the comma expression it created. VarDeclaration::semantic on tmp calls StructLiteralExp::semantic, which again sees Eins has destructor, so it does an another rewrite.
Eins devices = (Eins tmp = (Eins tmp2 = Eins(), tmp2), tmp);