I'm trying to wrap some legacy C code for use with C# running on .NET Core. I'm using the approach given here to create a C++ wrapper that compiles to pure MSIL. It's working well for simple functions, but I've found that if my code ever uses pointers-to-pointers or arrays of pointers it will crash with a memory violation. Often it crashes Visual Studio and I have to restart everything, which is tedious.
For example, the following code will cause the crashes:
public ref class example
{
public:
static void test() {
Console::WriteLine("\nTesting pointers.");
double a[5] = {5,6,7,8,9}; //Array.
double *b = a; //Pointer to first element in array.
Console::WriteLine("\nTesting bare pointers.");
Console::WriteLine(a[0]); //Prints 5.
Console::WriteLine(b[0]); //Prints 5.
Console::WriteLine("\nTesting pointer-to-pointer.");
double **c = &b;
Console::WriteLine(c == &b); //Prints true.
Console::WriteLine(b[0]); //Works, prints 5.
Console::WriteLine(**c); //Crashes with memory access violation.
Console::WriteLine("\nTesting array of pointers.");
double* d[1];
d[0] = b;
Console::WriteLine(d[0] == b); //Prints false???
Console::WriteLine(b[0]); //Works, prints 5.
Console::WriteLine(d[0][0]); //Crashes with memory access violation.
Console::WriteLine("\nTesting CLI array of pointers.");
cli::array<double*> ^e = gcnew cli::array<double*> (5);
e[0] = b;
Console::WriteLine(e[0] == b); //Prints false???
Console::WriteLine(b[0]); //Works, prints 5.
Console::WriteLine(e[0][0]); //Crashes with memory access violation.
}
}
Note that simply using pointers doesn't cause any problem. It's only when there is that extra level of indirection.
If I drop the code in a CLR C++ console app, it works exactly as expected and doesn't crash. The crash only happens when compiling the code into an MSIL assembly with clr:pure
and running from a .NET core app.
What could be going on?
Update 1: Here are the Visual Studio files: https://app.box.com/s/xejfm4s46r9hs0inted2kzhkh9qzmjpb It's two projects. The MSIL assembly is called library
and the CoreApp
is a C# console app that'll call the library. Warning, it's likely to crash Visual Studio when you run it.
Update 2: I noticed this too:
double a[5] = { 5,6,7,8,9 };
double* d[1];
d[0] = a;
Console::WriteLine(d[0] == a); //Prints true.
Console::WriteLine(IntPtr(a)); //Prints a number.
Console::WriteLine(IntPtr(d[0])); //Prints a completely different number.