gcc 优化给出无限循环或段错误
gcc optimization gives infinite loop or segfault
我刚刚发现了一个非常有趣的代码。 GCC 优化奇怪地改变了它的行为。
- -O0 有效
- -O1 段错误
- -O2 无限循环(从 7 到 1996,包括在内)
- -O3 有效
- -Og 段错误
- -Ofast 作品
代码如下:
int main(int argc, char *argv[])
{
int i, c;
c = 0;
for (i = 10; i < 10000; ++i)
{
if (is_lychrel(i))
++c;
printf("%d\n", i);
}
printf("%d\n", c);
return EXIT_SUCCESS;
}
函数is_lychrel(int)
使用参数。
据我所知,这可能是由于某处未定义的行为造成的,但我无法发现它。我试图禁用一些优化标志,但到目前为止我没有运气。
如果您需要更多代码,请随时询问。
编辑:
正如评论中所建议的那样,我尝试对一些功能进行评论,最后调试了旧学校的方式(因为 gdb 将无法工作)。我找到了罪魁祸首(至少是段错误):
void add_reverse(int d[], int *len)
{
int i;
int plus[28] = {0};
for (i = 0; i < *len; ++i)
{
//printf("d %d\n", i);
plus[i] = d[*len - i - 1];
}
add(d, plus, len);
}
假定此函数将一个数字(作为数字数组)添加到他的反向和 return 新长度。示例:({1, 2}, 2)
应该给出 ({3, 3}, 2)
。它不会与 printf
发生段错误,但不会给出好的结果。我正在尝试逐步分析 d[] 。 d[] 是 0034647260072070369072646341
就在段错误之前(似乎有效)。
编辑 2:
在 plus
的计算后添加一个简单的显示循环(显示一个是不够的)更正 -O1.
的输出
for (i = 0; i < *len; ++i)
printf("%d", plus[i]);
这里是 add()
代码,如果有帮助的话:
void add(int d[], int plus[], int *maxlen)
{
int i, of;
of = 0;
for (i = 0; i <= *maxlen; ++i)
{
d[i] += plus[i];
if (of)
{
d[i] += of;
of = 0;
}
if (d[i] >= 10)
{
of = 1;
d[i] %= 10;
}
}
if (d[i - 1])
++*maxlen;
}
简单。我的阵列太小了。出于某种原因,我确定尺寸,但我绝对错了。我应该先检查一下。
现在每个优化级别都可以正常工作。
我刚刚发现了一个非常有趣的代码。 GCC 优化奇怪地改变了它的行为。
- -O0 有效
- -O1 段错误
- -O2 无限循环(从 7 到 1996,包括在内)
- -O3 有效
- -Og 段错误
- -Ofast 作品
代码如下:
int main(int argc, char *argv[])
{
int i, c;
c = 0;
for (i = 10; i < 10000; ++i)
{
if (is_lychrel(i))
++c;
printf("%d\n", i);
}
printf("%d\n", c);
return EXIT_SUCCESS;
}
函数is_lychrel(int)
使用参数。
据我所知,这可能是由于某处未定义的行为造成的,但我无法发现它。我试图禁用一些优化标志,但到目前为止我没有运气。
如果您需要更多代码,请随时询问。
编辑: 正如评论中所建议的那样,我尝试对一些功能进行评论,最后调试了旧学校的方式(因为 gdb 将无法工作)。我找到了罪魁祸首(至少是段错误):
void add_reverse(int d[], int *len)
{
int i;
int plus[28] = {0};
for (i = 0; i < *len; ++i)
{
//printf("d %d\n", i);
plus[i] = d[*len - i - 1];
}
add(d, plus, len);
}
假定此函数将一个数字(作为数字数组)添加到他的反向和 return 新长度。示例:({1, 2}, 2)
应该给出 ({3, 3}, 2)
。它不会与 printf
发生段错误,但不会给出好的结果。我正在尝试逐步分析 d[] 。 d[] 是 0034647260072070369072646341
就在段错误之前(似乎有效)。
编辑 2:
在 plus
的计算后添加一个简单的显示循环(显示一个是不够的)更正 -O1.
for (i = 0; i < *len; ++i)
printf("%d", plus[i]);
这里是 add()
代码,如果有帮助的话:
void add(int d[], int plus[], int *maxlen)
{
int i, of;
of = 0;
for (i = 0; i <= *maxlen; ++i)
{
d[i] += plus[i];
if (of)
{
d[i] += of;
of = 0;
}
if (d[i] >= 10)
{
of = 1;
d[i] %= 10;
}
}
if (d[i - 1])
++*maxlen;
}
简单。我的阵列太小了。出于某种原因,我确定尺寸,但我绝对错了。我应该先检查一下。
现在每个优化级别都可以正常工作。