Я получаю ошибку SIGABRT, когда компилирую следующий код. (PRIME1 проблема spoj). Ссылка на проблему - http://www.spoj.com/problems/PRIME1/. Он хорошо работает с кодовыми блоками, но spoj возвращает ошибку SIGABRT. Может ли кто-нибудь объяснить причину?
int main()
{
long long k,x,j=0,size,l=0,p=0,q=0,r=0,s;
cin>>size;
int a[(2*size)];
cout<<endl;
for(int i=0; i< (2*size); i++)
{
cin>>a[i];
}
if( size == 1)
{
p=a[1];
}
else
{
do
{
if(a[l+3]>a[l+1])
{
p=a[l+3];
}
else
{
p=a[l+1];
}
l=l+2;
}while(l<2*(size-1));
}
cout<<p;
long * b = new long [p-1];
for(long long i=0;i<p-1;i++)
{
b[i]=1;
}
b[0]=b[1]=0;
s=sqrt(p)
for(long long i = 2; i <= s; i++)
{
if(b[i] == 1)
{
for(long long j = i*i; j <= p; j = j + i)
{
b[j] = 0;
}
}
}
while(r<(2*size))
{
for(long long i = a[r];i < a[r+1];i++)
{
if(b[i] == 1 )
{
cout << i << "\n";
}
}
cout<<endl;
r=r+2;
}
delete [] b;
}
int a[(2*size)-1];
Это не законный C++ код (он использует расширение GCC), но он, очевидно, скомпилирован, поэтому мы разрешим этот слайд. Вы получаете доступ к своему массиву за пределами диапазона в следующем цикле и повсюду в дальнейшем, что является неопределенным поведением - вам нужен массив размером 2 * size
для чтения во всех поставленных параметрах. Хотя при условии, что они гарантируют size <= 10
, вы можете просто объявить его как int a[20];
Но это, вероятно, не вызвало краха. Что вызвало крушение, вероятно, эта линия:
long * b = new long [p-1];
Что такое p
? Ну, давайте просто рассмотрим простой случай size = 1
где вы установите p
на a[1]
или на второе число, которое вы читаете. Каковы границы этого числа?
В вопросах говорится, что оценка равна n <= 1000000000
или 10 9. Ваш new
может запрашивать до 8 ГБ памяти, в зависимости от значения sizeof(long)
в используемой вами системе. Выделение почти наверняка будет терпеть неудачу, std::bad_alloc
исключение std::bad_alloc
которое вызывает std::bad_alloc
std::abort()
, поскольку у вас нет кода обработки исключений.
new
до массива , который может быть столь же большой , как 4 Гб (при условии 32-бит) с учетом ограничений , предусмотренных, которые просто не будут работать.
Вы инициализировать до a
2 * size - 1
элементов...
int a[(2*size)-1];
Но вы пишете элементы 2 * size
.
for(int i=0; i< (2*size); i++)
// ...
Ваша петля должна быть:
for(int i=0; i< (2*size-1); i++)
Следующий...
if(size == 1)
{
p=a[1];
}
Если size == 1
то вы выделили массив из 2 * 1 - 1 = 1
, поэтому a[1]
является недопустимым доступом (у вас есть только a[0]
как массивы 0-индексируются).
У вас тогда есть такие вещи:
if(a[l+3]>a[l+1])
Какая петля до l == 2*size-1
, поэтому l+3
недействителен, как только вы нажмете 2 * size - 1 - 3
.
В основном у вас просто много мест, где вы читаете или записываете конец конца массива или не обеспечиваете правильную инициализацию и вызывают неопределенное поведение.
Вы получаете доступ к элементу массива, обращающемуся за пределами границ
Размер массива 2*size-1
Итак, элементы от 0 до 2*size-2
Но в вашем цикле for вы увеличиваете 2*size
до 2*size
тем самым получаете доступ к 2*size-1
который находится за пределами границ
int a[(2*size)-1];
является (1) недопустимым C ++ (VLA является расширением GCC) и (2) неправильно вычисляет размер массива.