从 C++ 获取回调时,WinXP 中的内存限制是多少? C# 中的 DLL?
我有一个使用非托管 C++ DLL 的 C# 应用程序。我发现当我从 C++ DLL 传回的内存太大时,只会在 WinXP(而不是 Win7)中发生崩溃。
基本流程是,C# 通过调用启动函数来启动 C++ DLL 中的操作,并在该函数中提供回调。然后,C++ DLL 执行操作并将日志信息转储到文本缓冲区中。当操作完成时,C++ DLL 调用回调并将文本缓冲区作为参数传递:
C++:
typedef void (CALLBACK *onfilecallbackfunc_t)(LPCWSTR);
DLL_API void NWAperture_SetOnFileCallback(onfilecallbackfunc_t p_pCallback);
l_pFileCallback(_wstringCapture.c_str());
C#:
public delegate void FileCallback([MarshalAs(UnmanagedType.LPWStr)] string buffer);
public static extern void SetOnFileCallback(FileCallback fileCallback);
private void OnFile(string buffer);
这在 Win7 中工作正常,但在 WinXP 中如果缓冲区太大就会崩溃。我不确定导致此问题的确切大小,但我对其设置了 8MB 限制,并且崩溃已经消失。
有谁知道在 WinXP 中 C++ 和 C# 之间可以传输的内存量有限制吗?或者我完全误解了这个问题并且有更合乎逻辑的解释?
更新:我应该更具体 - 这发生在具有 WinXP 和 Win7 双启动的同一台 PC 上,均为 32 位操作系统。
I have a C# application that uses an unmanaged C++ DLL. I've found a crash that only happens in WinXP (not Win7) when the memory I'm passing back from the C++ DLL is too big.
The basic flow is that C# starts an operation in the C++ DLL by calling a start function, in which it provides a callback. The C++ DLL then performs the operation and dumps logging information into a text buffer. When the operation is completed the C++ DLL calls the callback and passes the text buffer as a parameter:
C++:
typedef void (CALLBACK *onfilecallbackfunc_t)(LPCWSTR);
DLL_API void NWAperture_SetOnFileCallback(onfilecallbackfunc_t p_pCallback);
l_pFileCallback(_wstringCapture.c_str());
C#:
public delegate void FileCallback([MarshalAs(UnmanagedType.LPWStr)] string buffer);
public static extern void SetOnFileCallback(FileCallback fileCallback);
private void OnFile(string buffer);
This works fine in Win7, but in WinXP if the buffer gets too big it crashes. I'm not sure of the exact size that causes this but I've put an 8MB limit on it and the crash has disappeared.
Does anyone know of a limit on the amount of memory that can be transferred between C++ and C# like this in WinXP? Or have I completely misunderstood this problem and there's a more logical explanation?
Update: I should have been more specific - this occurs on the same PC with WinXP and Win7 dual boot, both 32-bit OS.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
所以最终证明我是个白痴。为了使日志变大但加快测试速度,我单击了取消按钮,该按钮调用了 C++ DLL 中的一个函数,该函数停止执行并调用带有“中止”错误的回调函数以及已记录的任何日志。但是当我这样做时,执行并没有立即停止,因此当带有日志的回调正在进行时,C++ 代码可能会尝试添加到日志中。这导致了我所看到的不稳定。
我通过在日志周围使用关键部分来修复它。
So it eventually turned out I was being an idiot. In order to make the log large but speed the testing up I was clicking on the cancel button, which called a function in the C++ DLL that stopped execution and called the callback function with an 'abort' error and whatever log had already been recorded. But when I did this the execution didn't stop immediately, so when the callback with the log was in progress the C++ code could attempt to add to the log. This caused the instability I was seeing.
I fixed it by using a critical section around the log.
在实际用完 RAM 之前,您可能会用完连续内存。这是使用数组缓冲区的一大缺点。链接列表(或使用分块的数组)有助于缓解此问题,因为您需要的空间不必是连续的。
因此,除非您的应用程序使用 2+ GB 的 RAM,否则您的问题更有可能是内存碎片。
Windows 7 管理 RAM 的方式可能与 Windows XP 不同,这可能就是您没有看到问题的原因。但是推送更多数据,我相信您会遇到同样的问题。
您可以设置 perfmon 来跟踪/记录系统的内存使用情况,并设置任务管理器来跟踪您的应用程序。
You can run out of contiguous memory way before you actually run out of RAM. This is the one big down side of using Array buffers. LinkedLists (or arrays using chunking) help mitigate this issue, because the space you need doesn't have to be contiguous.
So unless your application is using 2+ GB of RAM, than your issue is more likely memory fragmentation than anything else.
Windows 7 is probably managing the RAM differently than Windows XP, that's probably why you're not seeing the problem there. But push more data through and I'm sure you'll run into the same issue there.
You can setup perfmon to track/log memory usage of your system and task manager to track your application.
我不知道 Windows 或 NETFX 设置了任何硬限制,但我非常怀疑从 C++ 应用程序返回的数据量可能完全是任意的,这可能会导致不稳定的行为。
我强烈建议考虑将日志数据写入本机组件中的文件,然后从托管代码中读取该文件。这样,无论记录多少数据,您的托管代码都可以解析它,而不必担心破坏其堆。
I'm not aware of any hard limit set by Windows or NETFX, but I am highly suspicious that the volume of data returned from your C++ app could be entirely arbitrary and this could result in volatile behavior.
I strongly recommend considering writing your log data to a file in your native component and then reading the file from your managed code. This way, it doesn't matter how much data is logged, your managed code can parse through it without worrying about blowing its heap.