我目前正在为 Windows MSVC++ (9.0) 应用程序(即异常结构和类型/继承、调用堆栈、错误报告和日志记录等)开发基于异常的错误报告系统。
我现在的问题是:如何正确报告和记录内存不足错误?
当这个错误发生时,例如bad_alloc
由操作抛出new
,可能有许多“功能”不可用,主要涉及进一步的内存分配。通常,如果异常已被抛出到一个库中,我会将其传递给应用程序,然后使用消息框和错误日志文件来报告和记录它。另一种方法(主要用于服务)是使用 Windows 事件日志。
我遇到的主要问题是组装一条错误消息。
为了提供一些错误信息,我想定义一个静态错误消息(可能是字符串文字,最好是消息文件中的条目,然后使用 FormatMessage)并包含一些运行时信息,例如调用堆栈。
此用途所需的功能/方法
- STL (
std::string, std::stringstream, std::ofstream
) - 阴极射线管 (
swprintf_s, fwrite
) - 或 Win32 API (
StackWalk64, MessageBox, FormatMessage, ReportEvent, WriteFile
)
除了在 MSDN 上记录之外,它们都在 Windows 中更多(Win32)或更少(STL)封闭源代码,所以我真的不知道它们在低内存问题下的表现如何。
只是为了证明可能有问题,我写了一个微不足道的小应用程序引发了 bad_alloc:
int main()
{
InitErrorReporter();
try
{
for(int i = 0; i < 0xFFFFFFFF; i++)
{
for(int j = 0; j < 0xFFFFFFFF; j++)
{
char* p = new char;
}
}
}catch(bad_alloc& e_b)
{
ReportError(e_b);
}
DeinitErrorReporter();
return 0;
}
运行了两个没有附加调试器的实例(在版本配置中,VS 2008),但“没有发生任何事情”,即我在错误报告中内部使用的 ReportEvent 或 WriteFile 中没有错误代码。然后,启动一个带调试器和一个不带调试器的实例,并让它们尝试通过在 ReportError 行上使用断点一个接一个地报告错误。对于附加了调试器的实例,这工作得很好(正确报告并记录了错误,即使使用 LocalAlloc 没有问题)!但是taskman表现出一种奇怪的行为,在应用程序退出之前释放了大量内存,我想是在抛出异常时。
请考虑可能有多个进程 [edit] 和多个线程 [/edit] 消耗大量内存,因此释放预分配的堆空间不是一个安全的解决方案,以避免要报告的进程的内存不足环境错误。
先感谢您!