One source file:
import std.stdio;
void main() {}
Compile with the following command line:
dmd -noboundscheck -inline -release -deps=temp.dep main.d
All arguments are needed, as is the import. main() is not.
Version 2.057
Comment #1 by clugdbug — 2012-03-30T17:14:49Z
It is crashing in AttribDeclaration::inlineScan(),
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
s->inlineScan(); // <---- crashes here
It isn't a null pointer, it seems to be an invalid vtable (memory corruption?)
Comment #2 by clugdbug — 2012-04-05T06:15:31Z
I can reproduce this on Windows7, but not on Linux64.
This is the worst heisenbug I've ever seen. Although it's possible to reduce the test case a bit, the reduction makes no sense -- changing an unused list of anonymous enums from 9 to 8 items makes the bug go away, for example.
It seems to be either a stack overflow or an out of memory condition, because the faulting location jumps around if you make changes to the test case.
Worse, some changes don't just crash; they cause the windows command prompt to hang afterwards.
Comment #3 by clugdbug — 2012-05-14T04:11:50Z
My test of this on Linux was incorrect. It happens there too.
valgrind shows the problem lies in this code (mars.c, line 1320)
if (global.params.moduleDeps != NULL)
{
assert(global.params.moduleDepsFile != NULL);
File deps(global.params.moduleDepsFile);
OutBuffer* ob = global.params.moduleDeps;
deps.setbuffer((void*)ob->data, ob->offset);
deps.writev();
------> note that file 'deps' has already been destroyed at this point!!!!
}
// Scan for functions to inline
if (global.params.useInline)
{
/* The problem with useArrayBounds and useAssert is that the
* module being linked to may not have generated them, so if
* we inline functions from those modules, the symbols for them will
* not be found at link time.
*/
if (!global.params.useArrayBounds && !global.params.useAssert)
{
// Do pass 3 semantic analysis on all imported modules,
// since otherwise functions in them cannot be inlined
for (size_t i = 0; i < Module::amodules.dim; i++)
{
m = Module::amodules[i];
if (global.params.verbose)
printf("semantic3 %s\n", m->toChars());
m->semantic3();
----> now semantic3 can encounter an import, which will add write to the outbuffer, that was already free'd.
I love valgrind.