Search code examples
cmacosmallocxcode5realloc

Malloc Error Caused by Realloc


I've been scratching my head over this for hours. I'm running Mac OS X 10.8, with XCode 5. I've been getting the following error:

malloc: *** error for object 0x1006487b8: incorrect checksum for freed object - object was            
probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug

Unfortunately, object 0x1006487b8 is freed at this point, and my debugger has no recollection of what was there.

The problem is, the error never occurs in the same place. I can only assume that a bit of memory isn't freed properly, and then the computer tries to use it for some other purpose and winds up confused.

My code is using SDL 2, and as far as I can tell, the only free -like function call occurs in the following form with a realloc:

static LGC_Gate* LGC_CreateEmptyGate(){
    if (!gates) {
        gates = malloc(sizeof(LGC_Gate));
        if (!gates)
            return NULL;
    }
    else{
        LGC_Gate* tmpgates = realloc(gates, sizeof(LGC_Gate) * (numgates + 1));
        if (tmpgates)
            gates = tmpgates;
        else
            return NULL;
    }
    numgates++;
    gates[numgates - 1].id = numgates - 1;
    return &(gates[numgates - 1]);
}

gates is a static, file-scope pointer to an array of gates and is declared as such at the top of the file:

static LGC_Gate* gates = NULL;
numgates is initialized to zero at the beginning of the file, and represents the number of gates currently in use. gates should always be of size numgates * sizeof(LGC_Gate).

My plan was to hold all gates created by the user in a single array, so that it was easy to tally them and get each at a moment's notice. The LGC_CreateEmptyGate function is used like this, for example:

LGC_Gate* LGC_InitActGate(LGC_Action act, uint8_t innum, uint8_t outnum){
    LGC_Gate* product = LGC_CreateEmptyGate();
    if (!product)
        return NULL;

    product->rule.type = LGC_FUNCTION;
    product->rule.act = act;

    product->input.used = innum;
    product->input.val = 0;
    product->output.used = outnum;
    product->output.val = 0;

    int i;
    for (i = 0; i < 8; i++) {
        product->inputfrom[i].active = 0;
    }

    return product;

}

Have I done something horribly wrong?

Update

I have done some debugging with the following code:

printf("%d\n", sizeof(LGC_Gate));
LGC_Gate* TestGates[5];
//Go through the gates, initialize each of them, record the value of their ptr,
//and if any are LESS than sizeof(LGC_Gate) apart, report an error.
int gcount;
for (gcount = 0; gcount < 5; gcount++) {
    TestGates[gcount] = LGC_InitActGate(LGC_NOR, 2, 1);
    printf("%p\n", TestGates[gcount]);
    if (gcount < 4) {
        if (TestGates[gcount] + sizeof(LGC_Gate) > TestGates[gcount + 1]) {
            printf("Error!");
            //TestGates[gcount + 1]->id = 4;  If this line were uncommented, 
            //                                BAD_ACCESS ensues.          
        }
    }
}

To my complete surprise, this actually outputs an error, and indeed crashes on some of the pointers. CORRECTION: The erroring pointer always seems to be the third one. Note that LGC_InitActGate calls LGC_InitEmptyGate once, and simply copies data for the rest of its duration. What is going on?

Update 2

Well, I believe I've discovered the error now. Every time realloc is called, the entire block of memory may or may not relocate, which renders the array of 5 pointers I had useless and pointing to old, freed memory. This makes total sense, but it's one heckuva bug. I should've noticed before. I'm not sure how to fix this, but thanks for the help I got.


Solution

  • Every time realloc is called from main, the memory block may or may not relocate, which leaves the array TestGates have elements that point to invalid memory.