Поэтому я столкнулся с некоторым странным поведением, которое я сократил до следующего минимального примера:
#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;
}
}
При компиляции с gcc 7.3.0 с помощью команды
c++ -Wall -O2 program.cpp -o program
я получаюпредупреждений нет.При запуске программы выдается следующий вывод:
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)
, что, по-моему, означает, что у меня наконец-то не хватило памяти для вектора.
Очевидно, что здесь что-то не так.Я предполагаю, что это как-то связано с тем фактом, что 2150000 * 1000 немного больше, чем 2 ^ 31, но это не так просто: если я уменьшу это число до 2149000, то программа будет работать так, как ожидается:
0
100
200
300
400
500
600
700
800
900
cout
не является необходимым для воспроизведения этого поведения, поэтому я предполагаю, что минимальный пример на самом деле
#include <vector>
int main()
{
std::vector<int> vec;
for(int i = 0; i < 1000; i++)
{
vec.push_back(2150000 * i);
}
}
Запуск этого приводит к тому, что программа долго ждет, а затем происходит сбой.
Вопрос
Я довольно новичок в C ++ на любом серьезном уровне.Я делаю что-то глупое, что допускает неопределенное поведение, и если да, то что?Или это ошибка в gcc
?
Я пытался это Google, но я не знаю, что с Google.
Приложение
Я вижу, что целочисленное переполнение (со знаком) - неопределенное поведение в C ++.Насколько я понимаю, это будет означать только то, что поведение выражения
21500000 * i
не определено, т. Е. Оно может принимать произвольное число.Тем не менее, мы можем видеть, что это выражение, по крайней мере, не меняет значение i
.