Как отмечалось в других ответах, OP испытывает комбинацию двух проблем: целочисленное переполнение и неограниченный доступ к вектору, обе причины неопределенного поведения.
Линия
int product = i * j;
Объявляет переменную int
, инициализированную с произведением i
и j
, которые имеют тип int
, в кавычках https://en.cppreference.com/w/cpp/language/types
Если длина отсутствуетприсутствуют модификаторы, ширина гарантированно не менее 16 бит.Тем не менее, в 32/64 битных системах ширина почти гарантированно равна 32 битам.
Очевидно, что в системе OP int
имеет 32-битную ширину, так чтозначение i
больше 46341 приводит к тому, что операция 46342 * 46342 = 2147580964 переполняет диапазон представимых чисел (вероятно, INT_MAX 2147483647).
В случае переполнения поведение не определено, но в большинстве архитектургде целые числа представлены в дополнении к 2, можно получить отрицательное число, что приводит к другой причине неопределенного поведения и, возможно, к «ошибке времени выполнения», упомянутой в вопросе:
if (array[product]) // <- 'product' can be negative
// 'array.at(product)' would have caught this error
{
array[product] = false;
//…
Простой способ предотвратитьэта проблема использует тип, достаточно большой для безопасного выполнения операции, такой как:
long long int product = static_cast<long long int>(i) * j;
Альтернативой является перезапись логики, чтобы избавиться от проблемной части:
#include <iostream>
#include <vector>
#include <cassert>
// Counts the number of prime numbers less than or equal to 'n'
long int count_primes(long int n)
{
if (n < 2)
return 0;
// Initialize the sieve. The first two elements (0 and 1) are ignored.
std::vector<bool> sieve(n + 1, true);
long int count = 0;
for (long int i = 2; i <= n; ++i)
{
// If a prime is found, delete all its multiples.
if ( sieve[i] )
{
// Update the counter, once only.
++count;
// Instead of performing a possible overflowing operation, you can
// use a bigger type, capable of store the result, or a different logic:
for (long int j = i + i; j <= n; j += i)
{
sieve[j] = false;
}
}
}
return count;
}
int main(void)
{
// Source: https://en.wikipedia.org/wiki/Prime-counting_function
assert(count_primes(1) == 0);
assert(count_primes(2) == 1);
assert(count_primes(10) == 4);
assert(count_primes(101) == 26);
assert(count_primes(1000) == 168);
assert(count_primes(10000) == 1229);
assert(count_primes(100000) == 9592);
assert(count_primes(1000000) == 78498);
std::cout << "So far, so good.\n";
}