2013-11-07 2 views
0

У меня есть программа для шифрования игрушек, которая сталкивается с ошибкой шины при предоставлении очень длинного ключа (я использую 961168601842738797, чтобы воспроизвести его), что меня озадачивает. Когда я прокомментировал разделы, чтобы изолировать ошибку, я обнаружил, что это вызвано этой невинно выглядящей петлей в моем Сите Эратосфена.Ошибка шины в C для Loop

unsigned long i; 
int candidatePrimes[CANDIDATE_PRIMES]; 
// CANDIDATE_PRIMES is a macro which sets the length of the array to 
// two less than the upper bound of the sieve. (2 being the first prime 
// and the lower bound.) 

for (i=0;i<CANDIDATE_PRIMES;i++) 
{ 

    printf("i: %d\n", i); // does not print; bus error occurs first 

    //candidatePrimes[i] = PRIME; 

} 

Временами это была ошибка сегментации, а не ошибка шины.

Может ли кто-нибудь помочь мне понять, что происходит, и как я могу это исправить или избежать этого в будущем?

Заранее благодарен!

PS

Полный код доступен здесь:

http://pastebin.com/GNEsg8eb

+1

Что такое 'CANDIDATE_PRIMES'? Большинство людей не уходят с сайта, чтобы посмотреть на ваш код. – John3136

+0

Его просто длина массива, моя ошибка. – Etsi

+1

Да, какая это ценность? 2, 20, 200, 2436492364934623905473843674383? – John3136

ответ

1

Проблема в том, что вы удаляете стек.

unsigned long i; 
int candidatePrimes[CANDIDATE_PRIMES]; 

Если CANDIDATE_PRIMES большой, это изменяет указатель стека на огромное количество. Но он не касается памяти, только настраивает указатель стека на очень большое количество.

for (i=0;i<CANDIDATE_PRIMES;i++) 
{ 

Это регулирует «i», который возвращается обратно в хорошую область стека и устанавливает его на ноль. Проверяет, что это < CANDIDATE_PRIMES, что и есть, и поэтому выполняет первую итерацию.

printf("i: %d\n", i); // does not print; bus error occurs first 

Это попытка поместить параметры для «printf» в нижнюю часть стека. БУМ. Недопустимое расположение памяти.

Какое значение имеет CANDIDATE_PRIMES?

И вы делаете Фактически хотите сохранить все штрихи, которые вы тестируете, или только те, которые проходят? Какова цель хранения значений 0 через CANDIDATE_PRIMES последовательно в массиве ???

Если вы просто хотели сохранить простые числа, вы должны использовать динамическое распределение и вырастить его по мере необходимости.

size_t g_numSlots = 0; 
size_t g_numPrimes = 0; 
unsigned long* g_primes = NULL; 

void addPrime(unsigned long prime) { 
    unsigned long* newPrimes; 
    if (g_numPrimes >= g_numSlots) { 
     g_numSlots += 256; 
     newPrimes = realloc(g_primes, g_numSlots * sizeof(unsigned long)); 
     if (newPrimes == NULL) { 
      die(gracefully); 
     } 
     g_primes = newPrimes; 
    } 
    g_primes[g_numPrimes++] = prime; 
} 
2

Я бы сказал ваш VLA слишком велик для вашего стека, что приводит к непредсказуемому поведению.

Лучше выделить массив динамически:

int *candidatePrimes = malloc(CANDIDATE_PRIMES * sizeof(int)); 

И не забудьте free перед возвращением.

Если это сито Eratosthenes, то массив действительно просто флаги. Нецелесообразно использовать int, если он просто держит 0 или 1. По крайней мере, используйте char (для скорости) или конденсируйтесь с битовой матрицей (для минимального хранения).

+0

Я реализовал его с флагами, но я завязал работу в этом. Преждевременная оптимизация была корнем всего зла, я решил быть расточительным и вернуться к нему позже. – Etsi

+0

Я только что посмотрел ваш код на pastebin. Вы должны определить макрос 'CANDIDATE_PRIMES' в круглых скобках, чтобы умножить работу. * ie * '#define CANDIDATE_PRIMES (n - FIRST_PRIME)'. Без этого у вас будут проблемы с кодом, который я предоставил. В стороне, пожалуйста, избавитесь от привычки чрезмерно удваивать ваш код. – paddy

+0

Двойной интервал в основном потому, что я добавлял и удалял printf(), но я буду помнить об этом. – Etsi

Смежные вопросы