【发布时间】:2014-08-20 18:12:24
【问题描述】:
这是一个基于多线程控制台的应用程序,在 Windows XP 上使用 MSVC2010 在 C++ 中开发。应用程序消耗大量内存。但是当内存使用量达到大约 2GB(Windows 32 位内存限制)时,它会突然在随机位置崩溃并出现以下错误:
- R6016- 线程数据空间不足
- 0xC0000005:访问冲突读取位置0x02030000
与之相伴的还有一个字符串多次出现在控制台“runtime error”。但不确定它来自哪里(我的代码没有打印出来)。
不幸的是,没有明确的堆栈跟踪或崩溃的可用位置。它只会在任何地方崩溃,尤其是当内存使用量达到 2GB 左右时。 我希望 CRT 在无法分配内存时返回错误或失败。在那种情况下,我确保应用程序能够顺利运行。但是为什么在这个地球上 显示带有这些错误的消息框,这些错误导致退出应用程序。
我为此挣扎了很多天,现在真的难以忍受。我试过了:
1) 通过调试器了解代码崩溃的位置。但它只是在任何地方崩溃。例如主要是在新的内存分配调用类似于:
char* ptr = new (std::nothrow) char[1024];
正如我们所见,任何应用程序都没有理由在此处崩溃。
2)缩小代码路径以找到崩溃的确切场景:我也无法成功。
作为一种解决方法,我认为不要将我的应用程序的内存使用量增加到 2GB。 但后来我想到一个问题,“有什么保证即使在低内存使用时也不会崩溃。这可能只是时间问题?”
另外,没有明确的方法可以提前知道how much exact memory is available 进行分配。
我真的被这个错误弄得筋疲力尽,迫切需要帮助/指导。
更新:
我缩小范围认为这是QueueUserWorkItem 的问题(Windows 函数将工作项排队到线程池中的工作线程)。当在没有内存的情况下进行调用时,它会导致线程内的内存分配失败并出现“运行时错误”不幸的是,我无法在此处给出重现此崩溃的示例代码,因为我通过第三方库调用该函数并且它非常很难从中提取代码进行演示。
但是为了解释,我调用了函数(带有标志WT_EXECUTELONGFUNCTION),当它完成时,它会从我再次调用它的地方调用回调(以便它可以处理下一个工作项)。
作为一种解决方法,我试图检查应用程序的内存使用情况(“私有字节”),而不是让它触及 2GB。希望它应该工作。
【问题讨论】:
-
我猜你的意思是
new(std::nothrow) char[1024]?另外,我猜您知道对于 32 位 Windows XP,应用程序可能使用的默认限制是 2GB(关键字IMAGE_FILE_LARGE_ADDRESS_AWARE)?因为它随机崩溃,我会说某些库中的一些new运算符(不在您自己的代码中)会导致您没有捕获的bad_alloc,或者库会默默地忽略它(从而导致访问冲突) . -
(Windows 32bit memory limit)这实际上不是内存限制,而是默认的用户地址空间限制,除非您使用 /LARGEADDRESSAWARE 链接器设置并使用 boot.ini 中的 /3GB 开关启动。 -
在应用程序崩溃时使用调试器停止(我认为 msvc 在默认情况下甚至会为访问冲突执行此操作)并向我们显示堆栈跟踪?
-
@Voo:调试器跟踪没有多大用处。因为大多数时候它显示在没有源的操作系统 DLL 中(并且没有显示到应用程序源的链接)
-
@Andrew 哦,源代码级调试无论如何都很古怪;)查看汇编代码可以说明很多事情,您也可以从 MS 获取 dll 的符号 - 尽管不知道 Visual Studio 是否可以做到这一点-我过去使用过windbg。
标签: c++ windows multithreading memory-management