为什么我的WinCE应用程序没有出现std::bad_alloc错误?

3
根据C++标准,当内存分配失败时operator new 应该抛出std::bad_alloc();。
为了测试这种行为,我想到了以下代码:
try
{
    for (;;)
    {
        Big* p = new Big;
        if (0 == p)
        {
            printf("nullptr");
            break;
        }
    }
}
catch (std::bad_alloc&)
{
    printf("exception");
}

问题是,每次在我的Windows Mobile 2003(Windows CE 4.2)上运行时,不期望地获取nullptr
编译器是Microsoft(R)C/C++优化编译器版本14.00.60131,因此我认为这不是编译器与标准不兼容的情况。
我还尝试在给定的try块中手动throw std::bad_alloc()(并成功),因此在new失败的情况下应该触发catch部分。另一件事是set_new_handler(),但也无效。如果这很重要,我的Big大小为10MB。
那么你能告诉我我错过了什么吗?为什么我没有得到std::bad_alloc编辑1: 我不是在寻找如何克服这个问题,而是想知道它首先发生的原因。 编辑2: 在调试new的旅程中,我尽可能简化了程序,并得到了反汇编输出:
        int* p = new int[10];
00011010  mov         r0, #0x28 
00011014  bl          00011040       <---- here is the call to operator new
00011018  str         r0, [sp, #0xC] 
0001101C  ldr         r3, [sp, #0xC] 
00011020  str         r3, [sp, #4] 
00011024  ldr         r3, [sp, #4] 
00011028  str         r3, p 

        operator new:
00011040  ldr         r12, [pc]           <---- 
00011044  ldr         pc, [r12]           <----  what are those?
00011048  andeq       r3, r1, r0          <----  is it just that?
0001104C  andeq       r1, r1, r4, lsr #11 <----  nothing else to be seen...     
00011050  streqd      r2, [r1], -r0       <----   

难道没有系统调用吗?这不应该更复杂吗?有人能帮忙调查一下吗?


可能存在低性能系统中异常处理过于昂贵的问题,导致标准遵从度不高。 - 111111
假设 Big 没有重载 new 运算符,那么它肯定不符合规范。可以尝试使用 struct Big2 { char big[10*1024*1024]; }; 来确认。你可以考虑使用 new (std::nothrow) Big,以提醒自己这就是你得到的行为。 - Steve Jessop
1个回答

3
这听起来很像MSVC6.0的行为,这并不奇怪,因为该平台的年龄。您可以在此处阅读更多信息。 MSDN Magazine September 2003 (CTRL-F查找bad_alloc)
您可以为Big覆盖new运算符,但我建议不要这样做,只需接受它实现不是很好,并继续尝试捕获std :: bad_alloc,在将代码移植到更好的平台时做好准备。
我通常不赞成使用宏,但您可以创建一个检查null并抛出bad_alloc的宏,如果您将代码移植,则可以快速删除它。(内联函数可能也可以解决问题,但有时需要一个丑陋的解决方案来解决一个丑陋的问题。)
template<PointerType>
inline void good_alloc(PointerTpye ptr) //throws std::bad_alloc
{
 #if BAD_COMPILER //MSVC version number?
     if(ptr==null)
     {
         throw std::bad_alloc; 
     }
 #else
     //do nothing
 #endif
}

实际上,可以通过提供一个new处理程序来使operator new()抛出异常 - 这可以通过set_new_handler()完成。 - sharptooth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接