C++/Windows:如何报告内存不足异常(bad_alloc)?

dyp*_*dyp 8 c++ windows error-reporting out-of-memory

我目前正在为Windows MSVC++(9.0)应用程序(即异常结构和类型/继承,调用堆栈,错误报告和日志记录等)开发基于异常的错误报告系统.

我现在的问题是:如何正确报告和记录内存不足错误?

当发生此错误时,例如,作为op bad_alloc抛出的错误,new可能存在许多"功能"不可用,主要涉及进一步的存储器分配.通常,我将异常传递给应用程序,如果它已经在lib中抛出,然后使用消息框和错误日志文件来报告和记录它.另一种方式(主要用于服务)是使用Windows事件日志.
我遇到的主要问题是汇编错误消息. 为了提供一些错误信息,我想定义一个静态错误消息(可能是字符串文字,更好的是消息文件中的条目,然后使用FormatMessage)并包含一些运行时信息,如调用堆栈.
这种使用所需的功能/方法也是如此

  • STL(std::string, std::stringstream, std::ofstream)
  • CRT(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;
}
Run Code Online (Sandbox Code Playgroud)

抛出两个没有连接调试器的实例(在Release config,VS 2008中),但"没有发生",即没有来自ReportEvent或WriteFile的错误代码我在错误报告中内部使用.然后,使用一个w/o调试器启动一个实例,让他们尝试使用ReportError行上的断点一个接一个地报告错误.对于连接了调试器的实例(正确报告并记录错误,即使使用LocalAlloc没有问题),这也很好!但是taskman展示了一个奇怪的行为,在应用程序退出之前释放了大量内存,我想当抛出异常时.


请考虑可能有多个进程[编辑]和多个线程[/ edit]消耗大量内存,因此释放预先分配的堆空间不是一个安全的解决方案,以避免想要报告的进程的低内存环境错误.

先感谢您!

pet*_*hen 2

  • 预先分配您需要的缓冲区
  • 静态链接并使用 _beginthreadex 而不是 CreateThread (否则,CRT 函数可能会失败) -- 或者 -- 自己实现字符串 concat / i2a
  • 使用 MessageBox (MB_SYSTEMMODAL | MB_OK) MSDN 提到了这一点来报告 OOM 情况(一些 MS 博主按预期描述了这种行为:消息框不会分配内存。)

日志记录比较困难,至少需要打开日志文件。

可能最好使用FILE_FLAG_NO_BUFFERINGFILE_FLAG_WRITE_THROUGH,以避免任何缓冲尝试。第一个要求写入和内存缓冲区是扇区对齐的(即,您需要查询 GetDiskFreeSpace,以此对齐缓冲区,并且仅写入“扇区大小的倍数”文件偏移量,并且写入扇区大小的倍数的块中。我不确定这是否有必要或有帮助,但每次分配都失败的系统范围 OOM 很难模拟。