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