У меня есть алгоритм для создания решета Эратосфена и получения по запросу начал от него. Это позволяет Вам ввести макс. значение для решета, и алгоритм дает Вам начала ниже того значения и хранит их в массиве c-стиля.
Проблема: Все хорошо работает со значениями до 500 000, однако когда я ввожу большое значение - при выполнении - оно дает мне следующее сообщение об ошибке в XCode:
Program received signal: “EXC_BAD_ACCESS”.
warning: Unable to restore previously selected frame.
Data Formatters temporarily unavailable, will re-try after a 'continue'. (Not safe to call dlopen at this time.)
Моя первая идея состояла в том, что я не использовал достаточно большие переменные, но как я использую 'неподписанное долгое длинное целое', это не должно быть проблемой. Также отладчик указывает на меня на точку в моем коде, где точке в массиве присваивают значение. Поэтому интересно, там максимальный предел массиву? Если да: я должен использовать NSArray вместо этого? Если не, то, что вызывает эту ошибку на основе этой информации?
Править: Это - то, на что код похож (это не завершено, поскольку это перестало работать в последней отправленной строке). Я использую сборку "мусора".
/*--------------------------SET UP--------------------------*/
unsigned long long int upperLimit = 550000; //
unsigned long long int sieve[upperLimit];
unsigned long long int primes[upperLimit];
unsigned long long int indexCEX;
unsigned long long int primesCounter = 0;
// Fill sieve with 2 to upperLimit
for(unsigned long long int indexA = 0; indexA < upperLimit-1; ++indexA) {
sieve[indexA] = indexA+2;
}
unsigned long long int prime = 2;
/*-------------------------CHECK & FIND----------------------------*/
while(!((prime*prime) > upperLimit)) {
//check off all multiples of prime
for(unsigned long long int indexB = prime-2; indexB < upperLimit-1; ++indexB) {
// Multiple of prime = 0
if(sieve[indexB] != 0) {
if(sieve[indexB] % prime == 0) {
sieve[indexB] = 0;
}
}
}
/*---------------- Search for next prime ---------------*/
// index of current prime + 1
unsigned long long int indexC = prime - 1;
while(sieve[indexC] == 0) {
++indexC;
}
prime = sieve[indexC];
// Store prime in primes[]
primes[primesCounter] = prime; // This is where the code fails if upperLimit > 500000
++primesCounter;
indexCEX = indexC + 1;
}
Как Вы можете или не можете видеть, то, что я - очень новичок. Любые другие предложения приветствуются, конечно, :)
Вы не переполняете переменные; вы переполняете стек. Когда вы создаете массив вроде int myArray [500]
, вы объявляете в стеке 500 int
s. Нормальный размер стека - 8 МБ. Только ваши два массива имеют размер около 8,4 МБ (8 байт * 550000 / (1024 ^ 2) = 4,2 МБ). Вместо этого вы должны использовать память кучи (из malloc ()
). Это будет примерно так:
int upperLimit = 550000;
unsigned long long *sieve = malloc(sizeof(long long) * upperLimit);
unsigned long long *primes = malloc(sizeof(long long) * upperLimit);
unsigned long long indexCEX;
unsigned long long primesCounter = 0;
Не забывайте, что вам нужно будет free ()
памяти, когда вы закончите с ней, или вы закончите утечку.
Насколько я знаю, "EXC_BAD_ACCESS" получается, когда вы пытаетесь работать с уже освобожденной памятью. Для отладки вы можете использовать класс NSZombie. Это может помочь: http://www.cocoadev.com/index.pl?DebuggingAutorelease
Вы используете массивы, выделенные на стеке. Вы можете выделить больше памяти, если используете динамическое распределение памяти:
/* program setup */
unsigned long long *sieve = malloc(sizeof(*sieve) * upperLimit);
unsigned long long *primes = /* -- "" -- */
/* etc, free() at program end */
Ограничение стека в вашей системе OS X, вероятно, составляет 8 Мб. Если sizeof(unsigned long long long) == 8
в вашей системе, то в стек поместится два массива по 500000 элементов, но не два массива по 550000 элементов.