gcc如何优化这个循环?

Dan*_*ury 8 c++ gcc g++ compiler-optimization undefined-behavior

所以我遇到了一些奇怪的行为,我将其分解为以下最小的例子:

#include <iostream>
#include <vector>

int main()
{
  std::vector<int> vec;

  for(int i = 0; i < 1000; i++)
  {
    vec.push_back(2150000 * i);
    if(i % 100 == 0) std::cout << i << std::endl;
  }
}
Run Code Online (Sandbox Code Playgroud)

使用命令使用gcc 7.3.0进行编译时

c++ -Wall -O2 program.cpp -o program
Run Code Online (Sandbox Code Playgroud)

我没有得到任何警告.运行该程序会产生以下输出:

0
100
200
300
400
500
600
700
800
900
1000
1100
1200
1300

[ snip several thousand lines of output ]

1073741600
1073741700
1073741800
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Aborted (core dumped)
Run Code Online (Sandbox Code Playgroud)

我猜这意味着我终于耗尽了内存的向量.

显然这里有些不对劲.我想这与2150000*1000略大于2 ^ 31这一事实有关,但它并不那么简单 - 如果我将这个数字减少到2149000,那么程序就会按预期运行:

0
100
200
300
400
500
600
700
800
900
Run Code Online (Sandbox Code Playgroud)

cout没有必要重现此问题,所以我想一个小例子,实际上是

#include <vector>

int main()
{
  std::vector<int> vec;

  for(int i = 0; i < 1000; i++)
  {
    vec.push_back(2150000 * i);
  }
}
Run Code Online (Sandbox Code Playgroud)

运行此程序会导致程序等待很长时间然后崩溃.

在任何严重的级别上,我都是C++的新手.我在这里做了一些愚蠢的事情,允许未定义的行为,如果是的话,是什么?或者这是一个错误gcc吗?

我确实试过谷歌,但我真的不知道谷歌会怎么做.

附录

我看到(带符号)整数溢出是C++中未定义的行为.据我所知,这只会意味着表达的行为

21500000 * i
Run Code Online (Sandbox Code Playgroud)

未定义 - 即它可以评估为任意数字.也就是说,我们可以看到这个表达式至少不会改变它的值i.

Dan*_*ury 5

为了回答我自己的问题,在检查汇编器输出之后,看起来g ++通过改变来优化这个循环

for(int i = 0; i < 1000; i++)
{
  vec.push_back(2150000 * i);
}
Run Code Online (Sandbox Code Playgroud)

喜欢的东西

for(int j = 0; j < 1000 * 2150000; j += 2150000)
{
  vec.push_back(j);
}
Run Code Online (Sandbox Code Playgroud)

我想这个加法比每个周期进行乘法更快,并且关于溢出是未定义行为的规则意味着可以进行这种改变而不必担心如果计算溢出,这是否会引入意外行为.

当然,优化循环中的条件总是失败,所以最终我最终得到的东西更像

for(int j = 0; true; j += 2150000)
{
  vec.push_back(j);
}
Run Code Online (Sandbox Code Playgroud)