Bug 11910 – Writes to extern (C) struct have no effect
Status
RESOLVED
Resolution
INVALID
Severity
major
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Windows
Creation time
2014-01-12T19:08:00Z
Last change time
2014-01-13T05:20:06Z
Assigned to
nobody
Creator
turkeyman
Comments
Comment #0 by turkeyman — 2014-01-12T19:08:24Z
Is this bad codegen, or have I done something wrong?
extern (C) struct MFDefaults
{
extern (C) struct InputDefaults
{
bool allowMultipleMice;
bool mouseZeroIsSystemMouse;
bool systemMouseUseWindowsCursor;
bool useDirectInputKeyboard;
bool useXInput;
}
InputDefaults input;
}
extern (C) __gshared MFDefaults gDefaults;
void f()
{
gDefaults.input.useXInput = false; // assignment has no effect
}
This code builds and links successfully. In the debugger I can inspect the values of the struct and they are correct, consistent with the struct in the C code.
But when I assign to anything, it simply has no effect...
Comment #1 by code — 2014-01-12T19:18:57Z
I checked the generated code on Linux x86_64 and it seems fine (store immediate zero in gDefaults at offset 4). So, more details and instructions to reproduce, please. ;)
Comment #2 by turkeyman — 2014-01-12T19:53:36Z
I'm building with DMD-Win64.
Digging further, I see this instruction in the debugger:
mov byte ptr [gDefaults+9Ch (7F685FBF01Ch)],1
Which looks correct...
But note, the debugger helpfully shows the calculated store address: 7F685FBF01Ch
&gDefaults.input.useXInput == 7F685FEBC7Ch
It should write to ...FEBC7Ch, but instead it writes to ...FBF01Ch, which is WAY before where it should be writing.
If I inspect the memory surrounding the address that it actually writes to, it is filled with things like fully justified D symbols (with module name and everything), path strings, lots of zeroes and float 1.0's. Not the structure I expect to see.
Comment #3 by turkeyman — 2014-01-12T20:00:13Z
(In reply to comment #2)
> I'm building with DMD-Win64.
>
> Digging further, I see this instruction in the debugger:
> mov byte ptr [gDefaults+9Ch (7F685FBF01Ch)],1
Note: +9C in mine is because my structure is actually much larger, I trimmed it down to log the bug. The offset 9C looks right.
The debugger also illustrated 'gDefaults' as the store address, which I guess means the address it writes to does match the symbol record in the debug info.
I guess the address emitted for gDefaults is wrong somehow?
But... that symbol should come from the external C library :/
Comment #4 by doob — 2014-01-13T02:43:57Z
(In reply to comment #3)
> Note: +9C in mine is because my structure is actually much larger, I trimmed it
> down to log the bug. The offset 9C looks right.
>
> The debugger also illustrated 'gDefaults' as the store address, which I guess
> means the address it writes to does match the symbol record in the debug info.
> I guess the address emitted for gDefaults is wrong somehow?
> But... that symbol should come from the external C library :/
What is "gDefaults" supposed to be? A symbol from a C library? In that case you forgot "extern", the correct declaration should be:
extern (C) extern __gshared MFDefaults gDefaults;
Have a look at: http://dlang.org/interfaceToC.html#C%20Globals
Comment #5 by turkeyman — 2014-01-13T03:31:27Z
(In reply to comment #4)
>
> What is "gDefaults" supposed to be? A symbol from a C library?
Yes, I thought that was clear from the 'extern (C)'.
> In that case you forgot "extern", the correct declaration should be:
>
> extern (C) extern __gshared MFDefaults gDefaults;
Umm... I think you need to look at the OP again.
Comment #6 by turkeyman — 2014-01-13T03:34:12Z
(In reply to comment #4)
>
> In that case you forgot "extern", the correct declaration should be:
>
> extern (C) extern __gshared MFDefaults gDefaults;
>
> Have a look at: http://dlang.org/interfaceToC.html#C%20Globals
... oh
Crap, where's that edit button!
Wow, I have no words.
I never would have spotted that a mile off, even when you said it!
That seems extremely redundant :/
Comment #7 by doob — 2014-01-13T04:20:35Z
(In reply to comment #6)
> ... oh
> Crap, where's that edit button!
>
> Wow, I have no words.
> I never would have spotted that a mile off, even when you said it!
>
> That seems extremely redundant :/
If you don't specify "extern" you get the storage of the variable in the D code.
Comment #8 by turkeyman — 2014-01-13T04:40:25Z
(In reply to comment #7)
> If you don't specify "extern" you get the storage of the variable in the D
> code.
Right, but shouldn't I have gotten a multiply defined symbols link error in that case?
* Marked resolved, user error! >_<
Comment #9 by doob — 2014-01-13T04:44:35Z
(In reply to comment #8)
> Right, but shouldn't I have gotten a multiply defined symbols link error in
> that case?
I think in some cases it just overrides the C symbol. Not overrides, but prefers the one in D. Walter has mentioned a couple of times this is possible. It might be a Windows/Optlink only thing.
Comment #10 by turkeyman — 2014-01-13T04:52:39Z
(In reply to comment #9)
> (In reply to comment #8)
>
> > Right, but shouldn't I have gotten a multiply defined symbols link error in
> > that case?
>
> I think in some cases it just overrides the C symbol. Not overrides, but
> prefers the one in D. Walter has mentioned a couple of times this is possible.
> It might be a Windows/Optlink only thing.
I'm linking against C code, so I have to use Win64 and the MS linker, which I'm very familiar with.
It may be that it just chose one, but curious to know why... anyway, all good. I'll look into that more closely later on.
False alarm, thanks for spotting my mistake! >_<
Comment #11 by doob — 2014-01-13T05:20:06Z
(In reply to comment #10)
> I'm linking against C code, so I have to use Win64 and the MS linker, which I'm
> very familiar with.
> It may be that it just chose one, but curious to know why... anyway, all good.
I found this on stackoverflow[1]:
"The linker will search the files you provide on the command line first for symbols, before it searches in libraries"
[1] http://stackoverflow.com/a/19023148/1787929