本机 C++ 的内存分配器C# 使用的库
我正在编写一些需要从 C# 调用的本机 C++ 代码(并且我无法用 C# 代码替换 C++ 本机代码)。
我在使用 malloc/free 在本机 C++ 代码中分配/释放一些内存时发现内存损坏。然后我使用 LocalAlloc/LocalFree 和 HeapAlloc/HeapFree 并遇到了同样的问题。
分配/解除分配似乎是正确的,并且它们发生在由本机代码创建的单独线程中。
我想知道在 C# 调用的本机 C++ 库中使用哪种最佳分配策略
编辑: 发现问题:问题不在分配/解除分配代码中,而是在正在写入的某些内存中被解除分配后。
I'm writing some native C++ code which needs to be called from C# (and I can't replace the C++ native code with C# code).
I found memory corruptions while allocating/deallocating some memory in the native C++ code using malloc/free. Then I used LocalAlloc/LocalFree and HeapAlloc/HeapFree and had the same problems.
The allocations/deallocations seem to be correct, and they happen in a separate thread, created by the native code.
I was wondering which is the best allocation strategy to use in a native C++ library called by C#
EDIT: found the problem: the problem wasn't in the allocation/deallocation code, but in some memory being written after being deallocated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
只要代码的 C# 端使用编译器的
/unsafe
开关和用于保存数据缓冲区的fixed
关键字,我认为应该没问题。至于内存分配的问题,可能不是 C++ 内存分配代码导致了问题,可能是 C++ 代码与驱动程序交互的方式......也许使用 VirtualAlloc/
VirtualFree
对,按照 MSDN 文档...编辑: 当您在与驱动程序交互后尝试分配缓冲区来保存来自 C++ 端的数据时...可能是竞争条件或中断延迟导致内存损坏...只是一个想法...
希望这会有所帮助,
此致,
汤姆.
As long as the C# side of the code uses the compiler's
/unsafe
switch and thefixed
keyword used for holding the buffer of data, I think you should be ok.As to the question of your memory allocation, it may not be the C++ memory allocation code that is causing the problem, it could be the way how the C++ code is interacting with the driver...maybe using
VirtualAlloc
/VirtualFree
pair as per the MSDN docs...Edit: When you try to allocate the buffer to hold the data from the C++ side after interacting with the driver...possibly a race-condition or interrupt latency is causing a memory corruption...just a thought...
Hope this helps,
Best regards,
Tom.
您的问题缺少基本细节,根本不清楚 C++ 代码分配的内存是否需要在 C# 端释放。这通常是通过 CLR 中的 P/Invoke 编组器或 COM 互操作层自动完成的。或者可以通过将方法参数声明为 IntPtr,然后使用 Marshal 类来手动完成。
如果它是自动完成的,则必须使用 COM 内存分配器 CoTaskMemAlloc()。如果您自己编组,也可以使用 GlobalAlloc(),在 C# 端使用 Marshal.FreeHGlobal() 进行释放。使用 GlobalAlloc() 没有任何优势,您不妨使用 CoTaskMemAlloc() 并使用 Marshal.FreeCoTaskMem() 进行释放。
但你自己应该注意到这一点。如果托管代码释放内存,则在 C++ 端使用 malloc() 或 HeapAlloc() 进行分配会导致泄漏而不是损坏。 Vista和Win7有一个更严格的堆管理器,如果发现错误的释放,它会终止程序。
在我看来,您的 C++ 代码中存在简单的堆损坏。这是非托管 C++ 编程最常见的祸害:超出缓冲区末尾、写入已释放的内存、错误的指针值。消除此类错误的方法是仔细检查代码并使用调试分配器,例如
提供的分配器。祝你好运。Your question is missing essential details, it isn't at all clear whether the memory allocated by the C++ code needs to be released on the C# side. That's normally done automatically with, say, the P/Invoke marshaller or the COM interop layer in the CLR. Or can be done manually by declaring a method argument as IntPtr, then use of the Marshal class.
If it is done automatically you must use the COM memory allocator, CoTaskMemAlloc(). If you marshal yourself you could also use GlobalAlloc(), release on the C# side with Marshal.FreeHGlobal(). There isn't any advantage to using GlobalAlloc(), you might as well use CoTaskMemAlloc() and release with Marshal.FreeCoTaskMem().
But you should have noticed this yourself. Allocating with malloc() or HeapAlloc() on the C++ side causes leaks instead of corruption if the managed code releases the memory. Vista and Win7 have a much stricter heap manager, it terminates the program if it notices a bad release.
It sounds to me that you have simple heap corruption in your C++ code. That is the most common scourge of unmanaged C++ programming, over-running the end of a buffer, writing to memory that's been freed, bad pointer values. The way to get rid of bugs like these is a careful code review and use of a debug allocator, such as the one provided by
<crtdbg.h>
. Good luck with it.Windows 驱动程序开发工具包建议不要使用 C++ 来编写驱动程序。
另外,最好的策略是让驱动程序管理自己的内存。当 c# 需要查看数据时,向其传递一个编组缓冲区并让驱动程序填充它
The windows driver developpement kit recommend against the use of C++ for drivers.
Also the best strategy is to have the driver manage its own memory. When the c# needs to see the data then pass it a marshalled buffer and have the driver to fill it