29

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

这个问题的想法是在与朋友的讨论中产生的。我们同意,通过故意在您提交的源代码中包含错误来破坏 cpp 项目必须相当简单......但我们能想到的最好的事情是使用未初始化的变量(导致运行时的随机分段错误) . 我敢肯定有更好的方法...?!

错误代码的通缉特征:

  • 乍一看必须像有效代码
  • 不能停止编译代码(太明显了)
  • 如果可能,错误应该看起来可能只是一个错误(应该找到它)
  • 错误必须严重到足以阻止软件发布(例如随机段错误、代码逻辑故障等)

尽管如此,虽然它必须引人注目,但在提交代码后它不应该是显而易见的......好吧,你明白了。

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

简而言之:

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

4

8 回答 8

17

经典的:

#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();
于 2013-01-10T23:59:44.473 回答
15

不太明显:

if (foo =! foobar)

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

 if ( (i =! 3) && (j==1))
于 2013-01-11T00:04:44.057 回答
9

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

作为说明,微软表示现在不要使用 MFC 容器,而是使用 STL 容器。

于 2013-01-11T01:05:08.603 回答
5

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

while(foo = bar) {}

代替

while(foo == bar) {}

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

荣誉奖:

  • 使用错误的数学运算符- + / *
  • 类似于=vs ==,误认为&for&&|for ||
  • 过早的优化vector<bool>(如果你都喜欢“什么?”,请阅读此处)
  • 有两个或多个具有相同名称的类并使用错误的类。
于 2013-01-11T00:00:34.010 回答
4

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

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

const unsigned char someBytes[] = "text\0abc123";

可以,用一个小开关,变成:

const unsigned char someBytes[] = "text\0123abc";

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

于 2013-01-11T00:48:44.497 回答
3

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

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

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

于 2013-01-11T00:33:49.210 回答
2
struct
{ int foo
char bar
}


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

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

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

2) 命名与预定义函数具有相似名称的函数

于 2013-01-11T01:05:45.860 回答
2

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

#ifdef NDEBUG
namespace {
    struct foo {
        foo() { sleep(rand() % 4); }
    } bar;
}
#endif
于 2013-01-11T01:19:48.350 回答