【发布时间】:2014-06-21 16:15:29
【问题描述】:
我有一个 c++ dll,它为我的主要 c# 应用程序提供一些功能。 在这里,我尝试读取一个文件,将其加载到内存中,然后将一些信息(例如指向加载数据的指针和内存块的计数)返回给 c#。 Dll 成功将文件读取到内存,但在返回主应用程序时,由于堆损坏导致程序崩溃(检测到严重错误 c0000374)。
代码非常简单明了,我之前做过一些类似的事情没有问题,但是我不知道是什么造成了这里的问题,我尝试使用“new、malloc 和 GlobalAlloc”分配内存,但也没有帮助。代码如下:
C++ MyDll:
typedef unsigned long U32;
extern "C" __declspec(dllexport) int ReadFile(LPSTR Path, U32** DataPtr, U32* Count)
{
FILE *fp;
U32 *Data;
CString tempStr(Path);
long fSize;
if(!(fp = fopen(tempStr, "rb"))) {
return 0;
}
// Obtain File Size;
fseek(fp, 0, SEEK_END);
fSize = ftell(fp);
rewind(fp);
Data = (U32 *)GlobalAlloc(0, fSize);
if(Data == NULL) {
fclose(fp);
return -1;
}
// Copy file into the buffer.
if(!(*Count = fread(Data, sizeof(U32), fSize / sizeof(U32), fp))) {
fclose(fp);
free(Data);
return -2;
}
*DataPtr = (U32 *)Data;
return 1;
}
C# 应用程序:
[DllImport(@"MyDll.dll", CallingConvention= CallingConvention.Cdecl)]
private static extern int ReadFile([MarshalAs(UnmanagedType.LPStr)]string Path, out IntPtr dataPtr, out uint Count);
private void readDump(string Path)
{
uint count = 0;
IntPtr Data = new IntPtr();
try{
if(ReadFile(Path, out Data, out count) == 1) //The Program crashes just right after this statement
{
//Do Something ...
}
}
catch() {}
}
程序在调试和发布模式下都会崩溃。除非我在加载文件后在调试模式下暂停程序并在“Visual Studio 的即时窗口”中调用一些内存块。 要加载的文件大小约为 64MB,PC 上有超过 2GB 的未使用内存。
更新:我注意到,他们之前运行的一些第三方程序会因“异常代码:c0000005”而崩溃,并且在 Windows 7(主机)中发生了一些其他奇怪的事情。所以我在另一个安装的 Windows 中测试了代码,一切似乎都正常工作。所以可能它与Windows 7有关。现在我该如何解决这个问题? "sfc /scannow" 找不到任何问题。
【问题讨论】:
-
fSize / 4 是错误的,如果你使用 GCC,它就不会是 4。我假设这会走下坡路,因为您忘记了 [DllImport] 属性中的 CallingConvention 属性,它是 Cdecl。写这样的代码根本没有意义,FileStream 也会这样做。
-
感谢您的评论,我将 "fSize / 4" 更改为 "fSize/sizeof(U32)" 和 "[DllImport(PCIiDllAddress)]" 更改为 [DllImport(PCIiDllAddress, CallingConvention= CallingConvention.Cdecl) ],但问题依然存在。我有充分的理由用 C++ 做一些工作,(这不是我的完整代码)。
-
C++ 在破坏堆时从来不会遇到太多麻烦。我猜问题出在我们看不到的代码中。在尝试与代码互操作之前,先对代码进行单元测试。
-
您在此处看到的所有代码都崩溃了。
-
我试图释放
const char*s。在将近一年的时间里,我发现free忽略了常量指针,所以我在内存上使用free时并不小心,因为这两者都可能是常量,也可能不是常量。出于某种原因,free不再忽略常量指针,而是对它们做了一些奇怪的事情。也许它试图释放可执行映像,或者它故意抛出堆损坏错误(也许它认为如果有人试图删除这种指针,一定是出了问题)。
标签: c# c++ dll dynamic-memory-allocation heap-corruption