Descubrí cómo escribir realloc, pero sé que el código no es correcto.

StackOverflow https://stackoverflow.com/questions/1641067

  •  08-07-2019
  •  | 
  •  

Pregunta

Lo que decidí hacer es

  • llamar a malloc
  • copie el bloque antiguo al bloque nuevo
  • libera el bloque viejo
  • y regrese el puntero al nuevo bloque

El código a continuación es lo que tengo hasta ahora ... pero sé que no está bien ... cualquier ayuda para arreglar el código sería muy apreciada ...

Si necesita más código del que he proporcionado, tengo una publicación anterior a esta que muestra todo el código. Soy nuevo, así que solo hay esta publicación y la última publicación que hice. Gracias.

void *mm_realloc(void *ptr, size_t size)
{
int i, p = *ptr;

 // make a call to malloc to find space
 //allocate memory

 ptr = malloc(size_t*sizeof(int));

 //copying old block to new block
 if(ptr!=NULL)
     for(i=0 ; i<size_t ; i++) 
     {
     *(ptr+i) = i;
     }

//freeing old block
free(ptr);

//return pointer to new block
return *ptr;
}
¿Fue útil?

Solución

Idealmente, un realloc () simplemente vería si hay suficiente memoria libre más allá del bloque actual y, de ser así, simplemente ajuste las estructuras de datos de la arena para expandir el bloque actual en el lugar. Esto elimina la costosa operación de copia y reduce las posibilidades de fallas en la asignación. Eso es para aumentar el tamaño. Para reducir, debe poder hacerlo siempre en el lugar, enviando el resto del bloque actual de vuelta al grupo libre.

Al hacer un malloc / free, si tienes 100K en la arena con un solo bloque de 60K asignado, llamar a tu mm_realloc para ajustar el tamaño a 50K fallará.

Sin embargo, es una solución viable , al menos para un primer intento, así que así es como la implementaría:

void *mm_realloc (void *ptr, size_t size) {
    int minsize;
    void *newptr;

    // Allocate new block, returning NULL if not possible.

    newptr = malloc (size);
    if (newptr == NULL) return NULL;

    // Don't copy/free original block if it was NULL.

    if (ptr != NULL) {
        // Get size to copy - mm_getsize must give you the size of the current block.
        // But, if new size is smaller, only copy that much. Many implementations
        // actually reserve the 16 bytes in front of the memory to store this info, e.g.,
        // +--------+--------------------------------+
        // | Header | Your data                      |
        // +--------+--------------------------------+
        //           ^
        //           +--- this is your pointer.
        // <- This is the memory actually allocated ->

        minsize = mm_getsize (ptr);
        if (size < minsize)
           minsize = size;

        // Copy the memory, free the old block and return the new block.

        memcpy (newptr, ptr, minsize);
        free (ptr)
    }

    return newptr;
}

Una cosa que notará que le falta a usted es que solo tiene que copiar suficientes bytes para el más pequeño de los bloques viejos y nuevos. De lo contrario, corre el riesgo de volcar el núcleo al desbordar uno de ellos.

Además, su bucle en realidad no copió los datos, estableció cada byte del bloque en su desplazamiento, y perdió el puntero antiguo al asignar el nuevo, de ahí mi uso de newptr para mantenerlos separados.

Otros consejos

Necesita saber qué tan grande es el bloque antiguo y el nuevo tamaño. Debe copiar el menor de los dos tamaños sobre el nuevo bloque.

También debe asegurarse de no destruir (liberar) el bloque anterior si falla el malloc (); simplemente devuelve 0.

Tampoco es necesario multiplicar el tamaño por 'sizeof (int)' en el malloc (); realmente está sobreasignando por un factor de 4 o más (en teoría, podría ser solo un factor de 2, pero pocas personas usan compiladores de 16 bits en estos días).

El punto de realloc es que intenta fusionar el bloque de memoria con uno libre detrás de eso, si es posible. Solo si no hay uno libre, asignará nueva memoria, copiará todo y liberará el bloque anterior.

¿Por qué estás escribiendo tus propias rutinas de asignación de todos modos?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top