Search code examples
cdynamic-memory-allocationundefined-behaviorrealloc

Dynamically allocated C array suddenly getting modified


I currently have a little project written in C here:

https://github.com/Nirma/clox/tree/virtual_machine

And have an issue where sometimes when this code runs:

int addValue(Chunk *chunk, Value value) {
    ValueArray *array = &chunk->values;
    if (array->capacity < array->count + 1) {
        array->capacity = GROW_CAPACITY(array->capacity);
        array->values = realloc(array->values, array->capacity);
    }

    array->values[array->count] = value;
    array->count++;
    return chunk->values.count - 1;
}

Another seemingly unrelated structure gets affected.

This code runs as expected but for some reason when these lines get uncommented:

    // location = addValue(&chunk, 500);
    // writeChunk(&chunk, OP_CONST, 1);
    // writeChunk(&chunk, location, 150);

the byte code array code held by Chunk gets corrupted but the address of the array remains the same.

int main(int argc, const char * argv[]) {
    Chunk chunk;
    
    initVM();
    initChunk(&chunk);
    int location;
    location = addValue(&chunk, 50);
    writeChunk(&chunk, OP_CONST, 123);
    writeChunk(&chunk, location, 123);
    
    
    location = addValue(&chunk, 150);
    writeChunk(&chunk, OP_CONST, 123);
    writeChunk(&chunk, location, 123);
    
    writeChunk(&chunk, OP_ADD, 123);
    writeChunk(&chunk, OP_NEGATE, 123);
    
    // location = addValue(&chunk, 500);
    // writeChunk(&chunk, OP_CONST, 1);
    // writeChunk(&chunk, location, 150);
    
    interpretChunk(&chunk);
    return 0;
}

I apologize for not summarizing the issue better but I'm not sure which area of the code is at fault so I posted a link to the project.

I am running this via Clang on Xcode on an arm64 machine.

Any tips or help would be greatly appreciated.

Thanks!

I tried the code posted above and was expecting:

// location = addValue(&chunk, 500); // writeChunk(&chunk, OP_CONST, 1); // writeChunk(&chunk, location, 150);

To simply add another instruction to push a constant onto the stack but instead had my bytecode array wiped clean.


Solution

  • At least this statement

    array->values = realloc(array->values, array->capacity);
    

    shall be rewritten like

    array->values = realloc(array->values, array->capacity * sizeof( Value ) );
    

    Though it would be more safer to use an intermediate pointer like for example

    Value *tmp = realloc(array->values, array->capacity * sizeof( Value ) );
    
    if ( tmp != NULL )
    {
        array->values = tmp;
        // and so on
    }