我有一个场景,我必须更新我的服务器操作系统版本和g ++版本,我发现工作正常的代码开始在新版本上给出错误(实际上是分段错误)。然后通过代码调试,我意识到有这样的事情:
#include<stdio.h>
int main()
{
char s[8]={'\0'};
sprintf(s,"overflow");
return 1;
}
汇编是g ++ file.cc -O2
因此,当我们分配整个字符串s时,优化会导致错误,并且没有NULL终止。我只是想问一下使用优化标志ON是一种好习惯,特别是在移动不同版本的g ++时,因为上面的错误可能会因为早期的错误编程实践而落实到位?
答案 0 :(得分:6)
错误在代码中;没有优化标志的事实你无法看到错误只是运气不好。
当然,优化器可能存在错误,但是当前的gcc只会极少地使用-O2
产生错误的代码。通常没有理由避免使用常见的优化标记。
此示例更多的原因是您应该更喜欢使用各种选项进行编译,最好使用一些内存检查选项和分析器,而不是避免优化的原因。
答案 1 :(得分:3)
错误是代码。代码具有未定义行为,它超出了分配内存区域的范围。你只是幸运/不幸,它之前没有表现出奇怪的行为而且现在只是表现出来。
这与优化标志的使用无关,只是一个显示未定义行为的错误代码的简单案例。
如果你的代码有未定义的行为,那么所有安全的赌注都会被取消,你只能确定一项法律,墨菲定律:
任何可能出错的事情,
答案 2 :(得分:2)
优化没有导致错误。对编译器版本和/或编译器配置的更改(在这种情况下可能是优化)会导致暴露现有错误。
由于此错误,您可能会在未来采取的良好做法可能是以下一项或多项:
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 - 为什么你需要在本地缓冲区中放置任何字符串而根本不用它?