"EXC_BAD_ACCESS: Unable to restore previously selected frame" Error, Array size?
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 ca开发者_开发技巧ll 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 :)
You're not overflowing the variables; you're overflowing the stack. When you create an array like int myArray[500]
, you're declaring 500 int
s 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.
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.
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
I also had this problem. Turns out I had loop. I was calling a method from within itself by accident.
精彩评论