问题
I have an algorithm for creating the sieve of Eratosthenes and pulling primes from it. It lets you enter a max value for the sieve and the algorithm gives you the primes below that value and stores these in a c-style array.
Problem: Everything works fine with values up to 500.000, however when I enter a large value -while running- it gives me the following error message in 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.)
My first idea was that I didn't use large enough variables, but as I am using 'unsigned long long int', this should not be the problem. Also the debugger points me to a point in my code where a point in the array get assigned a value. Therefore I wonder is there a maximum limit to an array? If yes: should I use NSArray instead? If no, then what is causing this error based on this information?
EDIT: This is what the code looks like (it's not complete, for it fails at the last line posted). I'm using garbage collection.
/*--------------------------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;
}
As you may or may not see, is that I am -very much- a beginner. Any other suggestions are welcome of course :)
回答1:
You're not overflowing the variables; you're overflowing the stack. When you create an array like int myArray[500], you're declaring 500 ints on the stack. The normal stack size is 8 MB. Your two arrays alone are about 8.4 MB (8 bytes * 550000 / (1024^2) = 4.2 MB). You should be using heap memory (from malloc()) here instead. So it would be like this:
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;
Don't forget that you'll need to free() the memory when you're done with it or you'll end up leaking.
回答2:
You are using arrays allocated on the stack. You can probably alloc more memory if you use dynamic memory allocation:
/* program setup */
unsigned long long *sieve = malloc(sizeof(*sieve) * upperLimit);
unsigned long long *primes = /* -- "" -- */
/* etc, free() at program end */
The stack limit on your OS X system is probably 8 MiB. If sizeof(unsigned long long) == 8 on your system, you'll fit two 500000-element arrays in your stack, but not two 550000-element arrays.
回答3:
As I know, "EXC_BAD_ACCESS" is received, when you try to work with already freed memory. To debug this you can use NSZombie class. This may help: http://www.cocoadev.com/index.pl?DebuggingAutorelease
回答4:
I also had this problem. Turns out I had loop. I was calling a method from within itself by accident.
来源:https://stackoverflow.com/questions/3051790/exc-bad-access-unable-to-restore-previously-selected-frame-error-array-size