Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"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 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 :)

like image 345
Job Avatar asked Jun 16 '10 08:06

Job


2 Answers

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.

like image 106
Chuck Avatar answered Nov 15 '22 06:11

Chuck


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.

like image 42
u0b34a0f6ae Avatar answered Nov 15 '22 08:11

u0b34a0f6ae