Comment #0 by verylonglogin.reg — 2012-11-15T00:59:34Z
---
void main(string[] args)
{
if(!args.length) return;
foreach(i; 0 .. 1)
main(null); // ok, C linkage used
foreach(i; 0 .. 1)
(&main)(null); // also ok
foreach(i; 0 .. 1)
{
auto p = &main; // D linkage used
p(null); // stack corruption, results in Access Violation
//asm { add ESP, 0x8; } // uncomment to fix
}
}
---
Note: do not mark `main` as `extern(C)` because it will lead to not calling runtime initialization stuff.
Comment #1 by maxim — 2012-11-15T01:49:06Z
I don't understand what is the problem here. First of all the code runs on both win&lin using dmd 2.060 and git head from Dpaste. Secondly I don't understand how this is related to linkage. Function calls main(null) and (&main)(null) are equivalent. In the third case you call it indirectly through pointer.
Comment #2 by verylonglogin.reg — 2012-11-15T02:01:22Z
(In reply to comment #1)
Sorry, it's calling convention, not linkage.
I mean C calling convention is used in first two cases but as `typeof(main)` tells it is `extern(D)` D calling convention is used in the last case.
So `Access Violation` isn't mandatory but possible.
I.e. this will print decreasing ESP:
---
import std.stdio;
void main(string[] args)
{
if(!args.length) return;
size_t esp;
foreach(i; 0 .. 2 ^^ 20)
{
auto p = &main; // D linkage used
p(null); // stack corruption, results in Access Violation
//asm { add ESP, 0x8; } // uncomment to fix
asm { mov esp, ESP; }
writefln("%X", esp);
}
}
---
Comment #3 by maxim — 2012-11-15T03:11:18Z
Ok, I see the problem now:
-------------------------
import std.stdio;
void main(string[] args)
{
dain(args);
if(!args.length) return;
foreach(i; 0 .. 2)
{
size_t esp;
main(null); // ok, C linkage used
asm { mov esp, ESP; }
writeln("main");
writefln("%X", esp);
}
foreach(i; 0 .. 2)
{
size_t esp;
(&main)(null); // also ok
asm { mov esp, ESP; }
writeln("&main");
writefln("%X", esp);
}
foreach(i; 0 .. 2)
{
size_t esp;
auto p = &main; // D linkage used
p(null); // stack corruption, results in Access Violation
//asm { add ESP, 0x8; } // uncomment to fix
asm { mov esp, ESP; }
writeln("p-main");
writefln("%X", esp);
}
}
void dain(string[] args)
{
if(!args.length) return;
foreach(i; 0 .. 2)
{
size_t esp;
dain(null); // ok, C linkage used
asm { mov esp, ESP; }
writeln("dain");
writefln("%X", esp);
}
foreach(i; 0 .. 2)
{
size_t esp;
(&dain)(null); // also ok
asm { mov esp, ESP; }
writeln("&dain");
writefln("%X", esp);
}
foreach(i; 0 .. 2)
{
size_t esp;
auto p = &dain; // D linkage used
p(null); // stack corruption, results in Access Violation
//asm { add ESP, 0x8; } // uncomment to fix
asm { mov esp, ESP; }
writeln("p-dain");
writefln("%X", esp);
}
}
----------------------------------
dain
18FDC4
dain
18FDC4
&dain
18FDC4
&dain
18FDC4
p-dain
18FDC4
p-dain
18FDC4
main
18FE10
main
18FE10
&main
18FE10
&main
18FE10
p-main
18FE08
p-main
18FE00
This is windows output. Note in main %esp is decreasing in last loop.
Same code on linux is fine (http://dpaste.dzfl.pl/6aa48fed), so this is specific to windows codegen/calling conventions.
Comment #4 by github-bugzilla — 2012-11-15T06:59:22Z