es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Redimensionando la memoria del heap

Entonces estoy intentando hacer un envoltorio muy simple alrededor de malloc() y realloc() para una solución perezosa a un recolector de basura. El problema es diseñar el búfer del recolector de basura. Quiero almacenar un puntero a punteros.

Así que necesitaría asignar inicialmente un tamaño arbitrario de memoria en la inicialización. El problema está dentro de esta función, creo. Quiero que esta función pueda redimensionar el búfer si detecta que está lleno. Pero actualmente, solo está contenta si tengo un búfer grande para no tener que usar esta función.

typedef struct ALLOC_STRUCT {
    void *cur_ptr;
    int index;
} alloc_T;

typedef struct GC_STRUCT {
    alloc_T **buffer; // Puntero que apunta a un array de punteros alloc_T.
    int count; // Tamaño del búfer.
} gc_T;

void gc_resize(gc_T *gc) {
    if (gc->count == 4 && gc->count != 0) {
        gc_T *new_gc = realloc(gc, (sizeof *new_gc) + sizeof(uintptr_t) * (gc->count + ALLOCATION));
        if (new_gc) {
            gc = new_gc;
            gc->buffer = realloc(gc->buffer, sizeof(uintptr_t) * (gc->count + ALLOCATION));
            gc->count = gc->count;
        } else {
            // Manejo de errores
        }
    }
}

Me preguntaba si este problema podría ser debido a demasiadas llamadas a realloc() (lo cual no creo que sea el caso) o si mi implementación del recolector de basura está mal. ¿Alguien puede encontrar algún problema?

Aquí está el código fuente si a alguien le interesa realmente:
https://github.com/Zernoxi/NewProgrammingLanguage/tree/memory_experiment/src

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Problema

    El problema con la implementación dada es que no está redimensionando correctamente el objeto gc. Cuando se pasa el objeto gc a la función gc_resize(), se pasa como un puntero. Sin embargo, gc es una copia local del puntero que apunta a la misma ubicación de memoria que el puntero original. Pero cualquier cambio realizado en gc dentro de la función gc_resize() no afecta al puntero original.

    Solución

    Para resolver este problema, la función gc_resize() debe tomar un puntero a puntero. Entonces, cualquier cambio realizado en el puntero desreferenciado se reflejará en el puntero original.

    Aquí está la función corregida:

    void gc_resize(gc_T **gc_ptr) {
        gc_T *gc = *gc_ptr;
        if (gc->count == 4 && gc->count != 0) {
            gc_T *new_gc = realloc(gc, (sizeof *new_gc) + sizeof(uintptr_t) * (gc->count + ALLOCATION));
            if (new_gc) {
                *gc_ptr = new_gc;
                new_gc->buffer = realloc(new_gc->buffer, sizeof(uintptr_t) * (new_gc->count + ALLOCATION));
                new_gc->count = new_gc->count + ALLOCATION;
            } else {
                // Manejo del error
            }
        }
    }
    

    Ahora, puedes llamar a la función gc_resize() con un puntero a un puntero para realizar cambios.

    gc_T *gc = malloc(sizeof *gc);
    gc->count = 0;
    gc->buffer = malloc(sizeof(uintptr_t) * STARTING_SIZE);
    
    // Llama a gc_resize() con un puntero a un puntero
    gc_resize(&gc);
    
    // Ahora gc tiene el tamaño de buffer actualizado
    

    ¡Espero que esto ayude!

Comments are closed.