【问题标题】:Does P/Invoke provide less memory to the target DLL?P/Invoke 是否为目标 DLL 提供更少的内存?
【发布时间】:2012-11-24 15:44:34
【问题描述】:

我的问题是我有一个无法修改的 32 位 DLL。在正常操作下,DLL 有时可能需要大约 1.5 gigs 左右的内存。

当我使用 C++/非托管代码测试程序时,DLL 只会在大约 2 gigs 时耗尽内存。这是预期的,因为这是 32 位进程可用的最大大小。因此,DLL 在正常运行下运行良好。

当我从本身占用大约 250 MB 的 C# 应用程序 P/Invoke DLL 时,当整个进程达到大约 1.4 gigs 时,DLL 会出错。我的问题是 P/Invoke 是否为 32 位进程提供了更少的内存供使用?有什么办法可以给它更多吗?

编辑:P/Invoked 函数实际上是从我的主程序集引用的 C# 程序集中调用的。不确定这是否有任何相关性。

【问题讨论】:

    标签: c# memory pinvoke dllimport


    【解决方案1】:

    差异可能是因为您的托管程序比非托管程序有更大的需求。因此留给 DLL 的资源就更少了。即使似乎还有内存,程序也可能会耗尽内存。当地址空间碎片化并且虚拟内存分配器找不到足够大的连续内存块来满足分配请求时,就会发生这种情况。

    我怀疑你无能为力。我怀疑您尝试使托管进程消耗更少的资源会很幸运。如果您在 64 位系统上运行并且您的进程可以识别大地址,那么您的进程可以访问 4GB 内存。

    将您的 .net 可执行文件标记为 LARGEADDRESSAWARE 可能会有所帮助。有关详细信息,请参阅另一个 SO 问题:How to make a .NET application "large address aware"? 总之,您需要运行EDITBIN 工具来标记您的可执行文件:

    EDITBIN /LARGEADDRESSAWARE YourExeName.exe
    

    请注意,尽管在 32 位操作系统上,您几乎会受到 2GB 的限制。是的,您可以使用 /3GB 开关启动系统,但通常不建议这样做。

    另一个明显的选择是将 DLL 存放在进程外 COM 服务器中。通过将其放在不同的进程中,您可以将 .net 运行时排除在进程之外,并为饥饿的 DLL 留出尽可能多的空间。

    【讨论】:

    • 它在 64 位机器上运行,但 DLL 是 32 位的。我可以将我的项目设为 64 位,但据我所知,这意味着我无法访问 32 位 DLL。此外,我提到的 1.4 gigs 是托管应用程序 + 进程的总内存(它们在任务管理器中合并显示),所以它仍然没有达到 2 gigs 的总和。
    • @Jasmin 我猜内存碎片正在发生,这就是它在 1.4GB 时失败的原因。看看您是否可以将您的托管应用标记为LARGEADDRESSAWARE,可能会有一些困难。
    • 非常感谢您对内存碎片的简要说明。可能就是这样。 LARGEADDRESSAWARE 似乎没有帮助 - 可能必须尝试您的其他解决方案。您是否知道在这种情况下,制作 CLI/C++ 包装 DLL 而不是直接从 C# 执行 P/Invokes 是否有好处?
    • 不,这无济于事。 P/invoke 不是很重的资源。剩下的 .net 野兽才是问题所在。你无法避免这种情况。我很惊讶 /LARGEADDRESSAWARE 没有帮助。
    • 使用 LARGEADDRESSAWARE 对我来说有很大的不同。我编写了一个简单的控制台应用程序,它分配了 32MB byte[] 对象。如果没有 LARGEADDRESSAWARE,我的 OOM 为 1.4GB。使用 LARGEADDRESSAWARE,它 OOM 为 2.7GB。你确定你没有在调用 EDITBIN 后重新编译?请记住,对 EDITBIN 的调用必须在构建 exe 之后
    【解决方案2】:

    这可能是因为您的 c++ 应用程序设置了 LARGEADDRESSAWARE 选项而 c# 应用程序没有

    在 c++ 应用程序中定义在这里 -> Linker->System-> Enable Large Addresses = "Yes/LARGEADDRESSAWARE"

    尝试添加以下构建后事件

    call "$(DevEnvDir)..\..\vc\vcvarsall.bat" x86
    "$(DevEnvDir)..\..\vc\bin\EditBin.exe" "$(TargetPath)"  /LARGEADDRESSAWARE
    

    【讨论】:

    • 如果 C++ 应用程序是 LARGEADDRESSAWARE,你会惊讶于它的 2GB 容量。
    • 感谢您的回复。 C++ 应用程序实际上并没有设置该标志,据我所知,到目前为止,在我的 C# 应用程序中设置它并没有帮助。
    猜你喜欢
    • 2022-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多