C++ 中最难发现的错误

most difficult-to-find errors in c++

本文关键字:错误 发现 C++      更新时间:2023-10-16

我很清楚,可能不会有"c++中最难发现的错误",但我仍然对其他人可以想到/可能已经遇到过的东西感兴趣。

这个问题的想法是在与朋友讨论时产生的。我们一致认为,通过在提交的源代码中欺骗性地包含错误来破坏 cpp 项目必须相当简单......但是我们能想到的最好的事情是使用未初始化的变量(导致运行时出现随机分割错误(。我相信有更好的方法...?!

错误代码的所需特征:

  • 第一眼必须看起来像有效的代码
  • 不能阻止代码编译(太明显(
  • 如果
  • 可能的话,错误应该看起来像它可能只是一个错误(如果发现(
  • 错误必须严重到足以阻止软件交付(例如随机 SEG 错误、代码逻辑故障等(

不过,虽然它必须引人注目,但在提交代码后不应该很明显......好吧,你明白了。

别担心,我们的考虑纯粹是理论上的(我们不打算破坏任何项目(。我们只是认为这是一个足够好的思想实验,可以与他人分享:-(

总之:

破坏源代码的最微妙方法是什么,这些源代码在差异提交(如 git(中可能被忽视,但最终会阻止软件的发布?

经典:

#define if while
#define else

埋在一些标题中。


干扰@WhozCraig的评论,也:

#define true (!!(__LINE__ % 10))

每十行一次true不会那么true,但编译程序的行为将保持一致......当来源发生变化时莫名其妙地改变。

沿着这条线:

#define for if(__LINE__ % 10) for
#define NULL (!(__LINE__ % 10))

或者呢:

#define virtual 

这将导致严重的问题 - 但仅在使用动态调度时,这可能会使其检测更加成问题。


以类似的方式:

#define dynamic_cast static_cast

// Fail early, fail often
#define throw std::abort();

不太明显:

if (foo =! foobar)

我们可以添加一个技巧来摆脱编译器警告:

 if ( (i =! 3) && (j==1))

我曾经被耽搁了大半个月,因为在发布版本中,对我们CArray进行排序(作为 MFC 的一部分Microsoft(会随机出现段错误,但调试版本很好。 我们用std::vector替换了它,问题解决了。 直到几个月后,有人告诉我CArray不使用元素赋值运算符,而是使用 memcpy(来源(。 这显然会使用非平凡赋值运算符损坏任何包含的对象,但它是一个标准容器,因此每个人都认为它是安全的。 因此,如果在几个关键的地方用CArray代替std::vector......

请注意,Microsoft说现在不使用 MFC 容器,而是使用 STL 容器。

我想

说的是,到目前为止,对我来说最令人沮丧的事情是使用=而不是==。 例如:

while(foo = bar) {}

而不是

while(foo == bar) {}

从本质上讲,任何导致代码无法正常工作而不是崩溃的事情都会让我把头撞到墙上。

荣誉奖:

  • 使用错误的数学运算符- + / *
  • = vs ==类似,将&误认为&&|误认为||
  • 过早优化类似vector<bool>(如果你们都喜欢"什么?
  • 具有
  • 两个或多个具有相同名称的类并使用错误的类。

也许是对这个问题的无耻盗窃,但我认为它非常适合这一类。

如果您有任何硬编码的字节字符串,所有长度都相同(例如,您可能与网络一起使用的东西(,您可以借此机会伪装它:

const unsigned char someBytes[] = "textabc123";

通过一个小开关,可以变成:

const unsigned char someBytes[] = "text123abc";

不同之处在于,由于中间的八进制文字,第一个只有 12 个字符,但第二个只有 10 个字符。如果出现这种情况,这无疑会加剧追查。

还没有成为

它的受害者,但隐式转换可能会导致一些不好的事情。看看这个:

class Foo {
public:
    Foo(int a, OtherClass* b = NULL);
};

现在(没有明确的关键字(每个期望通过值/常量引用的Foo的方法也将接受int!!

不是真正的错误,但是当我发现发布版本比调试版本慢时很烦人时,我会在随机源文件中的某个地方执行此操作。 :)

#ifdef NDEBUG
namespace {
    struct foo {
        foo() { sleep(rand() % 4); }
    } bar;
}
#endif
struct
{ int foo
char bar
}

while (foobar != 10);
{
     //do something here
 } 

1(忘记放一个;在结构之后或放置一个 ;在 WHILE 循环之后

randn() //user created function
rand()  //library function

2( 命名与预定义函数名称相似的函数