MFC error可能是堆被损坏,这也说明 XX.exe 中或它所加载的任何 DLL 中有 bug

来源:互联网 发布:高碳钢做刀怎么样知乎 编辑:程序博客网 时间:2024/05/16 15:23

今晚上调试了一晚上程序,总是显示“其原因可能是堆被损坏,这也说明。。。中或它所加载的任何DLL 中有bug”,终于在一篇文章中找到解决方法:

这是运行库文件时的错误。

解决方案:打开项目属性-->配置属性-->C/C++-->代码生成-->运行时库,改成多线程调试DLL

编译运行,然后可能会出项如下错误:

fatal error C1189: #error : Building MFC application with /MD[d] (CRT dll version) requires MFC shared dll version. Please #define _AFXDLL or do not use /MD


解决方案:打开项目属性-->配置属性-->常规-->项目默认值-->MFC的使用,选择“在共享 DLL 中使用 MFC”,就OK了~

如果上面这些都没用,那么就不是库文件运行的错误了,你可以试一下“清理解决方案”,然后重新生成,没准就行了。

 

在MSDN上有这么一篇文章“通过在DLL边界的潜在错误CRT对象

当通过 C 文件 (CRT)对象 (如文件句柄、区域设置和环境变量设置为或在 DLL 外部时 (在 DLL 边界函数调用),可能发生意外的行为,如果 DLL,以及调入 DLL 的文件,使用 CRT 库的不同副本。

一个相关,则会出现问题。您分配内存 (显式使用 newmalloc或隐式使用strdupstrstreambuf::str,等等) 后通过在将释放的 DLL 边界的指针。,如果 DLL 及其用户使用 CRT 库,不同的副本这可能导致内存存取冲突或堆损坏。

在调试期间例如,此问题的另一种症状将在输出窗口中的错误:

堆 []:无效地址指定要 RtlValidateHeap (#, #)

原因

CRT 库的每个副本都有一个个不同的状态。 因此, CRT 对象 (如文件句柄,环境变量和区域设置用于分发或设置这些对象 CRT 的副本才有效。当 DLL 及其用户使用 CRT 库中的不同副本,则在另一端无法通过在 DLL 边界的这些 CRT 对象和按预期方式正确会选取。

此外,,因为 CRT 库的每个副本都有自己的堆管理器,分配中存在一个 CRT 库中并传入 CRT 库的多个不同的副本会释放的 DLL 边界的指针是堆损坏的一个可能的原因。

如果您设计的 DLL,通过跨边界的 CRT 对象或分配内存并希望它在 DLL 外被释放,您限制 DLL 用户使用 CRT 库的同一副本与 DLL。,只有当两个与 CRT DLL,同一版本的链接到 DLL 及其用户使用 CRT 库的同一副本。这可能是问题,如果您使用 DLL 的 Visual C++ 5.0 混合由 Visual C++ 4.1 生成或更早版本的应用程序编译。由于 Visual C++ 4.1 使用的 CRT 库的 DLL 版本是 msvcrt40.dll,和可视使用的一个 5.0 是 msvcrt.dll,不能生成应用程序使用 CRT 库的同一副本。这些 DLL。

但是,也存在例外情况。 在美国英语版本和 Windows 2000 的其他一些本地化版本,例如德语、法语和捷克,该 msvcrt40.dll (4.20 版) 的代运方版本中提供。结果,因此,即使 DLL 与 msvcrt40.dll 链接,并且其用户与 msvcrt.dll 链接,则仍使用 CRT 库的同一副本,因为所有调用对 msvcrt40.dll 被转发到 msvcrt.dll。

但是 msvcrt40.dll 的此代运方版本不 Windows 2000 的某些本地化版本,如日语和中文、朝鲜语。 因此,因此,如果应用程序以这些操作系统,则需要用于获取不依赖于 msvcrt40.dll DLL 的已升级的版本或修改应用程序不依赖于使用 CRT 库的同一副本。如果您开发的 DLL,这意味着重新生成它与 Visual C++ 4.2 或更高版本。如果是第三方 DLL,需要与升级的供应商联系。

请注意 msvcrt40.dll (4.20 版) 的此代运方 DLL 版本无法重新发布。

示例

说明

此示例通过在 DLL 边界的文件句柄。

DLL 和 .exe 文件是用 /MD 编译,它们共享 CRT 的一个副本。

如果重新生成使用 /MT,以便使用 CRT 的单独副本,运行结果 test1Main.exe 导致访问冲突。

代码

// test1Dll.cpp // compile with: /MD /LD #include __declspec(dllexport) void writeFile(FILE *stream) { char s[] = "this is a string\n"; fprintf( stream, "%s", s ); fclose( stream ); }

代码

// test1Main.cpp // compile with: /MD test1dll.lib #include <stdio.h> #include <process.h> void writeFile(FILE *stream); int main(void) { FILE * stream; errno_t err = fopen_s( &stream, "fprintf.out", "w" ); writeFile(stream); system( "type fprintf.out" ); }

Output

this is a string
示例

说明

此示例通过在 DLL 边界的环境变量。

代码

// test2Dll.cpp // compile with: /MT /LD #include <stdio.h> #include <stdlib.h>__declspec(dllexport) void readEnv() { char *libvar; size_t libvarsize; _dupenv_s( &libvar, &libvarsize, "MYLIB" ); if( libvar != NULL ) printf( "New MYLIB variable is: %s\n", libvar); else printf( "MYLIB has not been set.\n"); free( libvar ); }

代码

// test2Main.cpp // compile with: /MT /link test2dll.lib #include <stdlib.h> #include <stdio.h>void readEnv(); int main( void ) { _putenv( "MYLIB=c:\\mylib;c:\\yourlib" ); readEnv(); }

Output

MYLIB has not been set.

如果 DLL 和 .exe 文件是用 /MD 编译,以便仅使用 CRT 的一个副本,程序平稳运行并产生以下输出:

New MYLIB variable is: c:\mylib;c:\yourlib

 

转自:http://hi.baidu.com/joyforce/item/9a80c5fd229168743d198b90

http://msdn.microsoft.com/zh-cn/library/ms235460.aspx

0 0
原创粉丝点击