c++ - C++ 成员函数中的 "if (!this)"有多糟糕?

标签 c++ visual-c++ gcc

如果我在应用程序中遇到 if (!this) return; 的旧代码,这风险有多严重?它是一个危险的定时炸弹,需要立即在整个应用程序范围内进行搜索和销毁工作,还是更像是一种可以安静地留在原地的代码气味?

当然,我不打算编写代码来做到这一点。相反,我最近在我们的许多应用程序使用的旧核心库中发现了一些东西。

想象一个 CLookupThingy 类有一个 非虚拟 CThingy *CLookupThingy::Lookup( name ) 成员函数。显然,在那个牛仔时代,其中一位程序员遇到了许多从函数传递 NULL CLookupThingy * 的崩溃,他没有修复数百个调用站点,而是悄悄地修复了 Lookup():

CThingy *CLookupThingy::Lookup( name ) 
{
   if (!this)
   {
      return NULL;
   }
   // else do the lookup code...
}

// now the above can be used like
CLookupThingy *GetLookup() 
{
  if (notReady()) return NULL;
  // else etc...
}

CThingy *pFoo = GetLookup()->Lookup( "foo" ); // will set pFoo to NULL without crashing

本周早些时候我发现了这颗 gem ,但现在我对是否应该修复它感到矛盾。这是我们所有应用程序使用的核心库。其中一些应用程序已经交付给数百万客户,而且似乎运行良好;该代码没有崩溃或其他错误。删除查找函数中的 if !this 将意味着修复数千个可能传递 NULL 的调用站点;不可避免地会遗漏一些,引入新的错误,这些错误将在接下来的开发中随机出现。

因此,除非绝对必要,否则我倾向于不理会它。

鉴于它在技术上是未定义的行为,if (!this) 在实践中有多危险?是否值得花费人工数周的时间来修复,还是可以指望 MSVC 和 GCC 安全返回?

我们的应用程序在 MSVC 和 GCC 上编译,并在 Windows、Ubuntu 和 MacOS 上运行。对其他平台的可移植性是无关紧要的。保证有问题的函数永远不会是虚拟的。

编辑:我正在寻找的客观答案类似于

  • “MSVC 和 GCC 的当前版本使用 ABI,其中非虚拟成员实际上是带有隐式 'this' 参数的静态成员;因此即使 'this' 为 NULL,它们也会安全地分支到函数中”或
  • “即将发布的 GCC 版本将更改 ABI,因此即使是非虚拟函数也需要从类指针加载分支目标”或
  • “当前的 GCC 4.5 有一个不一致的 ABI,有时它将非虚拟成员编译为带有隐式参数的直接分支,有时编译为类偏移函数指针。”

前者意味着代码很臭但不太可能破解;第二个是编译器升级后要测试的东西;后者需要立即采取行动,即使代价高昂。

显然,这是一个等待发生的潜在错误,但现在我只关心减轻我们特定编译器的风险。

最佳答案

我会不理它的。作为 SafeNavigationOperator 的老式版本,这可能是经过深思熟虑的选择。 .正如您所说,在新代码中,我不会推荐它,但对于现有代码,我会不理会它。如果你最终修改它,我会确保所有对它的调用都被测试很好地覆盖。

编辑添加:您可以选择仅在代码的调试版本中删除它:

CThingy *CLookupThingy::Lookup( name ) 
{
#if !defined(DEBUG)
   if (!this)
   {
      return NULL;
   }
#endif
   // else do the lookup code...
}

因此,它不会破坏生产代码的任何内容,同时让您有机会在 Debug模式下对其进行测试。

关于c++ - C++ 成员函数中的 "if (!this)"有多糟糕?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8842886/

相关文章:

c++ - 为什么 typeid.name() 使用 GCC 返回奇怪的字符以及如何使它打印未损坏的名称?

c++ - 将 boost::tokenizer 与 boost::iterator_range 结合使用

c# - 带有 Directx 11 的 WPF

c++ - 对模板基类成员函数的 undefined reference

visual-studio-2010 - Directx 9 在运行时编译着色器

c++ - 错误 : function declared 'noreturn' should not return

c++ - 终止工作线程和主线程之间的竞争条件

c++ - 我应该如何在 ATL 项目中创建类?

c++ - 查找内存分配错误

c++ - C++ 中 C 库的范围 - <X.h> 与 <cX>