【问题标题】:Why don't I get std::bad_alloc in my WinCE application?为什么我的 WinCE 应用程序中没有 std::bad_alloc?
【发布时间】:2011-12-05 16:53:56
【问题描述】:

根据 C++ 标准,operator new 应该在分配失败时throw 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++ Optimizing Compiler Version 14.00.60131 for ARM,所以我认为编译器不符合标准的情况并非如此。

我还尝试在给定的try 块内手动throw std::bad_alloc()(并且成功,因此catch 部分应在new 失败的情况下触发)。另一件事是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       <----   

不应该有任何系统调用吗?不应该更复杂吗?有人可以帮忙调查一下吗?

【问题讨论】:

  • 可能不符合标准,因为异常被视为低性能系统的两项费用。
  • 假设 Big 没有重载的 new 运算符,这绝对是不合格的。试试struct Big2 { char big[10*1024*1024]; }; 只是为了确定。您可以考虑改用new (std::nothrow) Big,只是为了提醒您这是您的行为。

标签: c++ assembly windows-ce arm bad-alloc


【解决方案1】:

这听起来很像 MSVC6.0 的行为,考虑到平台的时代,这并不奇怪。您可以在此处阅读更多相关信息。

MSDN Magazine September 2003 (ctrl-f for 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
}

【讨论】:

  • 实际上使operator new() 抛出可以通过提供new 处理程序来实现 - 这是通过set_new_handler() 完成的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-04
  • 2014-04-23
  • 1970-01-01
  • 2012-01-16
  • 2012-06-16
  • 2023-02-10
  • 2017-05-01
相关资源
最近更新 更多