C ++优化级别揭示了潜在的错误

时间:2012-01-29 08:11:26

标签: c++ c optimization

我有一个场景,我必须更新我的服务器操作系统版本和g ++版本,我发现工作正常的代码开始在新版本上给出错误(实际上是分段错误)。然后通过代码调试,我意识到有这样的事情:

#include<stdio.h>
int main()
{
        char s[8]={'\0'};
        sprintf(s,"overflow");
        return 1;
}

汇编是g ++ file.cc -O2

因此,当我们分配整个字符串s时,优化会导致错误,并且没有NULL终止。我只是想问一下使用优化标志ON是一种好习惯,特别是在移动不同版本的g ++时,因为上面的错误可能会因为早期的错误编程实践而落实到位?

7 个答案:

答案 0 :(得分:6)

错误在代码中;没有优化标志的事实你无法看到错误只是运气不好。

当然,优化器可能存在错误,但是当前的gcc只会极少地使用-O2产生错误的代码。通常没有理由避免使用常见的优化标记。

此示例更多的原因是您应该更喜欢使用各种选项进行编译,最好使用一些内存检查选项和分析器,而不是避免优化的原因。

答案 1 :(得分:3)

错误是代码。代码具有未定义行为,它超出了分配内存区域的范围。你只是幸运/不幸,它之前没有表现出奇怪的行为而且现在只是表现出来。

这与优化标志的使用无关,只是一个显示未定义行为的错误代码的简单案例。

如果你的代码有未定义的行为,那么所有安全的赌注都会被取消,你只能确定一项法律,墨菲定律

  

任何可能出错的事情,

答案 2 :(得分:2)

优化没有导致错误。对编译器版本和/或编译器配置的更改(在这种情况下可能是优化)会导致暴露现有错误。

由于此错误,您可能会在未来采取的良好做法可能是以下一项或多项:

  • 使用诸如valgrind之类的工具进行测试,以便更早地发现这些错误
  • 避免使用易于使用的sprintf()等功能,以支持使用有助于防止溢出的函数或类,例如snprintf()std::string

答案 3 :(得分:0)

代码有问题。优化不是原因。 sprintf在末尾添加了空字符,但s中没有足够的空格。

因此修复方法要么将s声明为:

char s[9]; //9 atleast!

或者,使用std::strncpy作为:

std::strncpy(s, "overflow", 8);

如果您要将s用作普通的c-string,请使用第一种方法。

答案 4 :(得分:0)

我想我无法理解您的问题 - 无论优化设置如何,上述错误都存在。您已经调用了未定义的行为 - 请感谢运行时能够合理地检测到它,而不是(例如)格式化您的硬盘驱动器。

解决方案不是为了避免编译器优化,而是为了避免首先调用UB。

答案 5 :(得分:0)

您提出的问题并不那么重要 - 您的程序依赖于未定义的行为。从这个意义上说,优化已经确定了一个错误,你应该为此感到高兴。

某些优化可能会引入错误(例如,假设所有浮点值都不是Inf或NaN),但这不是其中一种情况。

答案 6 :(得分:-1)

首先 - 这段代码没有任何用处。 第二 - 您将9个字节写入8字节缓冲区。 第三 - Ascii字符串必须以NULL结尾作为结束标记,并且没有地方可以将第9个代码放在8字节缓冲区中。 Forth - 为什么你需要在本地缓冲区中放置任何字符串而根本不用它?