【发布时间】:2018-12-13 08:06:30
【问题描述】:
我正在尝试封装一些旧的 C 代码,以便与在 .NET Core 上运行的 C# 一起使用。我正在使用the approach given here 创建一个编译为纯 MSIL 的 C++ 包装器。它适用于简单的函数,但我发现如果我的代码曾经使用指针指向指针或指针数组,它将因内存冲突而崩溃。它经常使 Visual Studio 崩溃,我必须重新启动所有内容,这很乏味。
例如,以下代码会导致崩溃:
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.
}
}
请注意,简单地使用指针不会导致任何问题。只有当有额外的间接级别时。
如果我将代码放到 CLR C++ 控制台应用程序中,它会完全按预期工作并且不会崩溃。只有在使用 clr:pure 将代码编译为 MSIL 程序集并从 .NET 核心应用程序运行时才会发生崩溃。
会发生什么?
更新 1: 以下是 Visual Studio 文件:https://app.box.com/s/xejfm4s46r9hs0inted2kzhkh9qzmjpb 这是两个项目。 MSIL 程序集称为library,CoreApp 是一个将调用库的 C# 控制台应用程序。警告,运行 Visual Studio 时可能会崩溃。
更新 2:我也注意到了这一点:
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.
【问题讨论】:
-
PITA 进行构建,但工作正常,正如预期的那样。这一点都不特别。
-
@HansPassant 您是否将其构建为纯 MSIL 程序集?然后从 .NET Core 应用程序调用?这些是它崩溃的唯一条件。如果构建为桌面 (.NET Framework) 应用程序或从桌面 (.NET Framework) 应用程序运行,它不会崩溃。
-
当然。如果您希望有人查看您的解决方案,那么您必须将其发布到某个地方。
-
@HansPassant 这是代码。它有两个项目。 “库”是 C++ CLI 中的上述代码,配置为编译为纯 MSIL。 CoreApp 是一个 C# 控制台应用程序,它将调用该库。我已经在几台电脑上试过了。它崩溃了,通常需要 Visual Studio。 app.box.com/s/xejfm4s46r9hs0inted2kzhkh9qzmjpb感谢收看!