c ++中最难发现的错误

时间:2013-01-10 23:57:30

标签: c++ runtime-error

我很清楚,可能不会出现“c ++中最难发现的错误”,但我仍然对其他人可能已经遇到过/可能已经遇到过的内容感兴趣。

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

故障代码的特征:

  • 必须在第一眼就看起来像有效代码
  • 不得停止编译代码(太明显)
  • 如果可能的话,错误看起来可能只是一个错误(应该找到它)
  • 错误必须严重到足以阻止软件发货(例如随机seg故障,代码的逻辑故障等)。

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

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

简而言之:

  

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

8 个答案:

答案 0 :(得分:15)

经典:

#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();

答案 1 :(得分:15)

不太明显:

if (foo =! foobar)

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

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

答案 2 :(得分:8)

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

作为一个说明,微软表示现在不使用MFC容器并使用STL容器。

答案 3 :(得分:4)

也许是this question的无耻盗窃,但我认为它在这一类别中非常适合。

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

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

可以通过一个小开关变为:

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

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

答案 4 :(得分:3)

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

while(foo = bar) {}

而不是

while(foo == bar) {}

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

尊敬的提及:

  • 使用错误的数学运算符- + / *
  • = vs ==类似,误导& &&| ||
  • vector<bool>Read Here之类的过早优化,如果你们都喜欢“什么?”)
  • 有两个或多个具有相同名称且使用错误的类。

答案 5 :(得分:2)

struct
{ int foo
char bar
}


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

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

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

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

答案 6 :(得分:2)

实际上并不是一个错误,但是当我发现版本比调试版本慢时,我发现这很烦人。 :)

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

答案 7 :(得分:1)

尚未成为它的受害者,但隐含的转换会导致一些不好的事情。看看这个:

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

现在(没有显式关键字)每个期望Foo by value / const引用的方法也会接受一个int !!!