Reduced test case:
extern(C) int printf(const char*, ...);
bool dtor = false;
struct S
{
int n;
void* get(void* p = null)
{
return null;
}
~this()
{
printf("dtor\n");
dtor = true;
}
}
S makeS(int n)
{
return S(n);
}
void foo(void* x)
{
throw new Exception("fail!");
}
void test(int len = 2)
{
foo(makeS(1).get());
// A temporary is allocated on stack for the
// return value from makeS(1).
// When foo throws exception, it's dtor should be called
// during unwinding stack, but it does not happen in Win64.
}
void main()
{
try
{
test();
} catch (Exception e) {}
assert(dtor); // fails!
}
I confirmed the issue on Win64, but I think it would happen in all platforms excepting Win32.
Currently dmd handles the destructor calls for temporaries by using OPdctor and OPddtor. It works correctly for Structural Exception Handling (SEH) in Win32.
On the other hand, Win64 and other Posix platforms generate exception handler tables and use them from druntime. However dmd generates them only for the explicit try-catch and try-finally statements, and doesn't recognize the implied try-block between OPdctor and OPddtor elements.
By that, throwing exception from 'foo' skips dtor call for the temporary in test().
It's an obstacle to my compiler fix for issue 14696.
https://github.com/D-Programming-Language/dmd/pull/4749
Comment #1 by ketmar — 2015-06-17T16:45:11Z
GNU/Linux x86 fails too, as expected.
p.s. but GDC works. +1 to Iain! ;-)
Comment #2 by github-bugzilla — 2015-09-02T08:56:36Z
FWIW dmd currently emits SEH wrappers around any temporary destruction.
Weird that nobody yet noticed that. Doesn't this severely impact performance on Win32?
Comment #5 by github-bugzilla — 2015-09-23T11:01:09Z
@WalterBright created dlang/dmd pull request #11676 "fix Issue 14708 - destructor for temporary not called during stack un…" fixing this issue:
- fix Issue 14708 - destructor for temporary not called during stack unwinding
https://github.com/dlang/dmd/pull/11676
Comment #9 by dlang-bot — 2020-09-09T22:25:01Z
dlang/dmd pull request #11676 "fix Issue 14708 - destructor for temporary not called during stack un…" was merged into master:
- 206fa12a6754a04d12c9e2ac0e6028c6dfa92b9a by Walter Bright:
fix Issue 14708 - destructor for temporary not called during stack unwinding
https://github.com/dlang/dmd/pull/11676