P/Invoke 和内存相关的间歇性崩溃
Posted
技术标签:
【中文标题】P/Invoke 和内存相关的间歇性崩溃【英文标题】:P/Invoke and memory related intermittent crash 【发布时间】:2014-11-18 12:11:03 【问题描述】:我前段时间实现了这个 API,一切运行良好,直到几周前我注意到它,间歇性崩溃,与 .NET 相关的著名编组“试图读取或写入受保护的内存。这通常是表明其他内存已损坏”。我注意到我打开的应用程序的数量也有一定的模式,所以我假设它与内存有关。但是检查可用内存,它在崩溃时仍然指向健康状态。请看下面的功能:
C++
__declspec(dllexport) char* xReadData(char *p_buffer, int offset, int size)
// do nothing
return p_buffer;
C#
[DllImport(PathToDll, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr xReadData([Out] IntPtr buffer, int offset, int size);
// SIZE = amount of bytes to read (2^13)
IntPtr pnt = Marshal.AllocHGlobal(SIZE);
...
try
xReadData(pnt, 0, SIZE); >> crashing on [Managed to Native Transition]
catch
...
Marshal.FreeHGlobal(pnt);
根据我的分析,它在本机函数完成和再次返回托管代码之间崩溃。
提前致谢。
【问题讨论】:
欢迎来到 Stack Overflow!建议查看提出此类问题的指南:***.com/help/mcve 完全忽略本机代码中的 size 参数当然肯定会造成麻烦。是的,当您执行此操作时,AccessViolations 是正常的。 这是编辑部分的错字。现已更正。 问题仍然存在。我希望我包括了所有需要指出问题所在的部分。 【参考方案1】:if ((offset>-1) && (offset + size<= MAX_BYTES))
memcpy(p_buffer, &(input_list[offset]), size);
当offset
等于MAX_BYTES
并且size 等于0 时,该条件肯定会抛出异常。
input_list[MAX_BYTES]
超出范围。
另外,我希望你释放缓冲区:-')
【讨论】:
感谢您的回复。这是真的,一个潜在的错误,只是在这种情况下偏移参数总是按值传递并且为 0。我很确定崩溃不在本机代码中,因为我确实分析了它。 我释放了缓冲区,真的。在它崩溃的时候,它甚至没有那么远来释放缓冲区。它只是在本机函数完成和再次返回托管代码之间崩溃。 @Allegro07;调试时使用分治法。开始一件一件地摆脱这些东西。摆脱memcpy
,看看崩溃是否仍然存在,如果是?那么那部分与问题无关。为什么你的方法返回的 IntPtr
和你传入的一样?
目前这是c++函数的设计,不是我的作品,我同意这很愚蠢,但这不是重点。我避免了 memcpy 操作并且崩溃仍然存在于某处,但这是一个很好的反馈,以便改进问题输入数据并排除 memcpy。
@Allegro07,我能告诉你的真的不多。创建一个新的测试项目,看看您是否可以重现您遇到的问题。看看不从函数返回任何东西是否会使它变得更好。此外,明确设置 C++ 端的调用约定。不要依赖编译器默认值。 __declspec(dllexport) __cdecl
或其他。改变哪些参数?你总是打电话(0,CONSTANT_SIZE)吗?您是否从不同的线程访问它?您在帖子中所说的这种“某种模式”是什么。以上是关于P/Invoke 和内存相关的间歇性崩溃的主要内容,如果未能解决你的问题,请参考以下文章