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.

Reply via email to