access violation With dll?
Adam D. Ruppe via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Thu Jul 16 12:43:21 PDT 2015
On Thursday, 16 July 2015 at 17:04:09 UTC, Taylor Hillegeist
wrote:
> void function(ref char[], int) Testf
> = cast(void function(ref char[], int))
> GetProcAddress(h, "Test"); //Function Says HELLO WORLD
>
> char[] STUFF;
> STUFF.length = 5000;
> Testf( STUFF , STUFF.length);
>
> printf("%s\n", (&STUFF)); //PRINTS HELLO WORLD
Just to go a little deeper into what is happening here, we'll
convert the D features into C features and understand what it
sees.
A D array, `char[]`, is seen in C as: `struct char_array { size_t
length; char* ptr; }`. A D `ref` is seen in C as a pointer.
So, your function there, in C, would look like:
void function(struct char_array *arr, int);
Which isn't what you were hoping for... so what happened when you
called it was the C side got:
Testf((char*) &STUFF, 5000);
Which runs... but what is &STUFF? It is one of those char_array
structs sitting on the stack! Which is only 8 bytes long.
So when the C function wrote out HELLO WORLD\0, your D array got
smashed with:
length = (size_t) 'LLEH';
ptr = (char*) 'ROW ';
And the 'LD\0' went right out of bounds and wrote over whatever
else was on the stack next (which is probably the HMODULE so when
you called FreeLibrary, it tried to free junk and caused the
access violation, but I'm not sure, you could load up a debugger
and try to find out, but the main point is that it overwrote
memory that it wasn't supposed to!).
The printf, however, ran because you made the same mistake twice
- passing &STUFF to it, while wrong, just passed the data your
last call clobbered.... coincidentally being valid enough to
print out.
Then the extern(C) vs extern(D) thing can come into play, but
here you just lucked out.
So yeah to avoid this in the future, be sure all those things
match the way C sees them - ref and arrays are generally wrong
there, use plain pointers instead.
More information about the Digitalmars-d-learn
mailing list