启动 dll 时 C# 环境堆栈溢出

C# environment stack overflows when starting dll

本文关键字:堆栈 栈溢出 环境 dll 启动      更新时间:2023-10-16

我有一个C#程序加载了一个dll函数:

[DllImport("/Users/frk/Workspaces/MySharedLibrary.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto, EntryPoint = "MyCFunction")]
public static extern int MyFunction( [In][MarshalAs(UnmanagedType.I4)]MyFormat format,  [In][MarshalAs(UnmanagedType.LPArray)] byte[] myString,  [In][MarshalAs(UnmanagedType.I4)] int myStringLength, [MarshalAs(UnmanagedType.LPArray)] byte[] output,  ref UIntPtr outputLength);

并称它

int result = MyFunction(format, inPut, inputLength, outPut, ref outputLength);

在C++方面,我有:

MyCPPFunction,从C测试可执行文件调用时可以完美运行。MyCPPFunction在其依赖项的深处包含一个在匿名命名空间中声明和初始化的全局常量变量:

namespace
{
constexpr unsigned RandTileSize = 256;
std::array<unsigned, RandTileSize * RandTileSize> GenerateSamples()
{
std::array<unsigned, RandTileSize * RandTileSize> samples;
std::mt19937 rd(0);
std::uniform_int_distribution<unsigned> distribution(0, 255);
for (unsigned i = 0; i < RandTileSize * RandTileSize; ++i)
{
samples[i] = distribution(rd);
}
return samples;
};
const auto samples = GenerateSamples();<-- Option#1 this causes a stack overflow when loading the dll in C# environment
unsigned Sample(unsigned index)
{
static const auto samples = GenerateSamples();<-- Option#2 this works and dll loads correctly
return samples[index];
}
}

我在这里感到困惑,因为 afaik,选项 1 应该在 dll 的代码部分分配内存,C# 环境应该正确处理?

我们如何在加载dll时有选项#1不引起内存分配问题?

DLL 中函数中静态变量的生存期是从第一次遇到语句到 DLL 卸载为止。

类或文件范围的变量的生存期是从加载 DLL 的时间到卸载的时间。

这样做的结果是,在失败的情况下,初始化代码正在运行,而 DLL 正在加载过程中。

在类构造函数中运行非平凡代码通常不是一个好主意,因为在加载程序锁中可以安全执行的操作存在限制。

特别是,如果执行任何需要动态加载另一个 DLL 的操作(例如LoadLibrary或调用延迟加载链接函数(,则可能会导致难以诊断的问题。

如果不确切诊断您的案例中出了什么问题,答案很简单:使用选项 2 或选项 3。

选项 3:

void MyDLLInitialize(){
// Initialize the dll here
}
void MyDLLUninitialize(){
// Uninitialize the dll here
}

然后分别在使用任何其他 DLL 函数之前和完成这些函数之后从 C# 调用这些函数。