锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 英语翻译 / 检测到致命错误C0000374-C++DLL返回给C#的指针指向无效内存
服务方向
人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发
联系方式
固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft
头条号:软件技术及人才和养生
人工智能QQ群:14372360

锐英源精品开源心得,转载请注明:“锐英源www.wisestudy.cn,孙老师作品,电话13803810136。”需要全文内容也请联系孙老师。


检测到致命错误C0000374-C++DLL返回给C#的指针指向无效内存


前言


最近用MFC写项目,里面主线程用对象,内存正常,把对象放子线程里就出各种各样的错误,错误还很不直观,比较难解决,这时候需要大家单步执行,每行代码都执行,定位到代码再分析。本文就是我查错时,从国外网站上找到参考,翻译下供大家参考。


提问

I have a c++ dll which serving some functionality to my main c# application. Here i try to read a file, load it to memory and then return some information such as the Pointer to loaded data and count of memory blocks to c#. The Dll reads file to memory successfully but on the return to the main application, program crashes due to Heap Corruption(Critical error detected c0000374).我有一个c++ dll,它为我的主要c#应用程序提供一些功能。在这里,我尝试读取文件,将其加载到内存,然后将一些信息(如加载数据的指针和内存块计数)返回到c#。Dll成功将文件读取到内存,但在返回主应用程序时,程序因堆损坏而崩溃(检测到严重错误c0000374)。

The code is quite simple and straightforward and I have done some similar things before with no problem, However i could not figure out what makes the problem here, I tried to allocate memory using "new, malloc and GlobalAlloc" but neither did help. Codes are as follow:代码非常简单明了,之前我做过类似的事情没有问题,但是我无法弄清楚是什么原因导致问题,我尝试使用“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# Application:

[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() {}

}

The program crashes on both debug and release mode. Unless I pause the program in debug mode after loading the file and call some blocks of memory in the "Visual Studio's Immediate window". The size of files to be loaded are around 64MB and we have more than 2GB unused ram on the PC.程序在调试和发行模式下都崩溃。除非我在加载文件后在调试模式下暂停程序并在“Visual Studio的立即窗口”中调用一些内存块。要加载的文件大小约为64MB,我们PC上有超过2GB未使用的RAM。

UPDATE: I noticed that, some third party programs which they working before, crash with "Exception Code: c0000005", and some other weird things happens in Windows 7 (the Host). so I tested the code in another installation of windows and everything seems to work as they should. So probably it's related be the Windows 7. Now how could I fix the problem? "sfc /scannow" failed to find any issue.更新:我注意到,他们之前工作的一些第三方程序崩溃了“异常代码:c0000005”,还有一些其他奇怪的事情发生在Windows 7(主机)中。所以我在另一个Windows安装中测试了代码,一切似乎都应该工作。所以它可能与Windows 7有关。现在我该如何解决这个问题呢?“sfc / scannow”找不到任何问题。

fSize / 4 is wrong, it won't be 4 if you use, say, GCC. I assume this goes down hill because you forgot the CallingConvention property in the [DllImport] attribute, it is Cdecl. There is no point at all in writing code like this, FileStream will do it just as well。fSize/4错了,如果你使用GCC,它将不会是4。我认为这是因为忘记了[DllImport]属性中的CallingConvention属性,它是Cdecl。在编写这样的代码时没有任何意义,FileStream也会这样做。

Thanks for your comment, I changed "fSize / 4" to "fSize/sizeof(U32)" and "[DllImport(PCIiDllAddress)]" to [DllImport(PCIiDllAddress, CallingConvention= CallingConvention.Cdecl)], but problem still exists. I have good reasons to do some jobs in c++, (this is not my complete code).感谢您的评论,我将“fSize / 4”更改为“fSize / sizeof(U32)”和“[DllImport(PCIiDllAddress)]”更改为[DllImport(PCIiDllAddress,CallingConvention = CallingConvention.Cdecl)],但问题仍然存在。我有充分的理由在c++中找问题(这不是我的完整代码)。

C++ never has much trouble corrupting the heap. I guess the problem is located in the code we cannot see. Unit-test the heck out of the code first before you try to interop with it。C ++破坏堆永远不会有太多麻烦。我想这个问题位于我们看不到的代码中。在尝试与其进行互操作之前,首先对代码进行单元测试。

I was trying to free const char*s. For nearly a year I have found free to ignore constant pointers, so I haven't been careful about using free on memory that both could have been or may have not been constant. For some reason free no longer ignores constant pointers but instead does something strange with them. Perhaps it tries to deallocate the executable image, or perhaps it was intentionally throwing the heap corruption error (maybe it thought something must have gone wrong if someone would try deleting a pointer of this sort)我试图释放const char*s。近一年来,我发现free忽略了常量指针,所以我一直没有注意free在内存上使用它们可能已经或可能不是一直不变的。出于某种原因,free不再忽略常量指针,而是对它们做了一些奇怪的事情。也许它试图释放可执行映像,或者它可能是故意抛出堆损坏错误(也许它认为如果有人试图删除这种指针就必须出错)

回答

If all your code is indeed what is shown above, then I don't see the problem. However, when I get this issue, sometimes its because malloc/new/whatever detects heap corruption, often this corruption has already occurred previously in the program, but the crash has been delayed until the next call to new/malloc.如果您的所有代码确实如上所示,那么我没有看到问题。但是,当我遇到这个问题时,有时候因为malloc / new / 或类似操作会检测到堆损坏,通常这个损坏已经发生在程序中,但是崩溃一直延迟到下一次调用new / malloc。

If you read other files, or allocate or free other buffers before the above is executed and crashes, I would look there for problems. Perhaps throw a bunch of asserts anywhere you write to buffers and check the bounds and what you are writing for overruns. Sorry this isn't a concrete answer, I do not have enough rep to leave this advice as a comment.如果您在执行上述操作并崩溃之前读取其他文件,或者分配或释放其他缓冲区,我会在那里寻找问题。也许在你写入缓冲区的任何地方抛出一堆断言,检查边界以及你要为溢出写的内容。对不起,这不是具体的答案,我没有足够的代表留下这个建议作为评论

Actually I'm not sure about the problem, but as i said in the update and after this time and program working perfectly, I figured that this problem was just happening in my old installation of windows, so I reinstalled the windows and problem had gone实际上我不确定这个问题,但正如我在更新中说的那样,在这段时间和程序运行完美之后,我认为这个问题刚好发生在我旧的Windows安装中,所以我重新安装了Windows并且问题已经消失了

This was my issue, I was overrunning a std::vector earlier in the code but puzzling over why free was crashing这是我的问题,我在代码中早些时候加强了std :: vector,但令人费解的是为什么free会导致崩溃

I dont think that this answer is correct. the C# IntPtr is a managed object... the GlobalAlloc() in c++ allocates an array on the heap, then assigns the ptr to that memory to the pointer pointed to by the new C# IntPtr. In fact, I wrote a test to prove it. I can't really paste the code here in a comment, but passing an out IntPtr to a native function, and assigning a U32* to it, in exactly the way the OP does, works flawlessly - I was able to read the correct values (which I wrote in the c++ side) out and print them on the managed c# side我不认为这个答案是正确的。C#IntPtr是一个托管对象... c ++中的GlobalAlloc()在堆上分配一个数组,然后将ptr分配给该内存到新C#IntPtr指向的指针。事实上,我写了一个测试来证明它。我无法在注释中粘贴代码,但是将IntPtr传递给本机函数,并以与OP完全相同的方式为其分配U32 *,完美无瑕地工作 - 我能够读取正确的值(我在c ++方面写的)并在托管的c#端打印出来

友情链接
版权所有 Copyright(c)2004-2021 锐英源软件
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州大学北校区院(文化路97号院)内