【问题标题】:Invalid pointer handling policy无效的指针处理策略
【发布时间】:2015-03-31 06:11:11
【问题描述】:

我认为如果在函数中传递了空指针,就让它gp,我们可以很容易地找到根本原因。但是我的队友说我们应该避免生产代码中的 gp 时间,如果应用程序通常崩溃,客户可能会感到不安,尽管根本原因可能会被一些空指针保护所覆盖。

当您需要验证指针是否为空时,您会使用哪种方法?

HRESULT function(const int* pNumber)
{
    { POINTER CHECK for pNumber... }
    ...
}

方法一 - 忽略无效的情况

if(pNumber)
{
    int a = *pNumber;   
}   
  • 没有 GP
  • 可能进入异常流
  • 很难找到根本原因

方法 2 - 断言指针,调试模式下的警告

assert(pNumber);
int a = *pNumber;
  • 5 月 GP 处于发布模式
  • 切勿进入异常流
  • 容易找到根本原因

方法 3 - 留下调试信息并返回错误代码

if(!pNumber)
{
    OutputDebugString(L"Error Null pointer in function.\n");
    return E_POINTER;
}
  • 没有 GP
  • 切勿在函数内部进入异常流。客户端忽略返回的E_POINTER可能会进入异常流外
  • 很难找到根本原因

方法 4 - 抛出 logic_error 异常 - 让调用者捕获

if(!pNumber)
{
    throw std::logic_error("Null pointer of pNumber in function");
};
  • 没有 GP
  • 堆栈展开时,如果没有资源管理 (RAII),代码序列中可能会发生资源泄漏。
  • 切勿进入异常流
  • 很难找到抛出异常的地方

【问题讨论】:

  • 一般保护错误,一般是在引用无效地址或0x00000000时,应用程序立即中止或崩溃。
  • 如果您将 GP 大写并且至少提及一次您想要它的意思,您的问题会有所改善。也就是说,由于您使用的是 C++,显然是方法 5,传递一个引用,这将强制调用者首先验证他们的指针。
  • @UlrichEckhardt 你应该这样回答:)

标签: c++ pointers


【解决方案1】:

如果您取消引用 nullptr,您将进入未定义行为的领域。这意味着,您的编译器没有义务执行anything sensible,因此应该避免这种情况。它也可能决定,因为它是非法的,所以它从未发生过,所以它删除了相应的代码(并因此对其进行了优化)并且你有逻辑错误而不会遇到一般保护错误。

如果nullptr 绝对无效,我个人更喜欢assert-case,但在这种情况下,无论如何引用可能更明智。我不认为有一个普遍的政策,因为它很大程度上取决于周围的逻辑。

【讨论】:

    【解决方案2】:

    例外是严重违反合同,如果您有两个通过接口通信的模块,这是有道理的。对于 cpp 单元本地的静态函数来说,抛出它并没有那么多。考虑访问结束后的数组。它还假设对方会抓住它。

    其他任何一个都不够好。

    • assert(pNumber); 一个人很弱。可能有一种行为是 特定于发布模式,你不会抓住它。此外它是 仅限于您在调试中测试过的输入范围(远 全部)。
    • 忽略上面显示的无效大小写是把你的头插入到 像鸵鸟一样接地。
    • OutputDebugString 比断言弱。你的开发者最终会让 事情会随着错误消息滑动,你会习惯这么多 将停止阅读它们。

    所以如果我不使用异常,我会使用

    assert(pNumber);
    if(pNumber)
    {
    
    }
    else
    {
       //Log with a logger which has different logging level to the level you seem fit 
    }
    

    【讨论】:

      【解决方案3】:

      我喜欢方法2

      assert(pNumber);
      int a = *pNumber;
      

      因为,在调试模式下,您可以轻松识别断言失败发生的位置。即使在释放模式下,它也保证空值不会继续进入函数内部。用户不会看到任何异常行为,应用程序将正常工作。

      【讨论】:

      • assert如何影响发布模式下的程序?我认为断言在发布模式下被删除。
      • C++中没有“调试模式”和“发布模式”之类的东西,它们是MSVCisms。但是,如果宏 NDEBUG#defined,则会删除 assert(),并且此宏通常是为优化(非调试)构建定义的。
      猜你喜欢
      • 1970-01-01
      • 2011-03-22
      • 2018-10-22
      • 2012-01-10
      • 1970-01-01
      • 1970-01-01
      • 2016-06-29
      • 2019-02-06
      • 2016-08-19
      相关资源
      最近更新 更多