Estoy tratando de crear una matriz dinámica simple de estructuras, pero no estoy seguro de cómo hacerlo.
tengo
n = 1; typedef struct { char wordName [50]; int counter; }Words; Words * array;Y ahora quiero reasignarlo en este ciclo.
if(strlen(token) > 6){ array = (Words*)realloc(array, sizeof(Words)*n++); strcpy(array->wordName, token); //printf("%s ", array->wordName); array++; }Puedo agregar datos a la estructura, lo imprime todo en un bucle muy bien. Pero cuando agrego array++, obtengo:
realloc(): invalid pointer¿Estoy accediendo a los datos de forma incorrecta? ¿O ni siquiera tengo más punteros más allá de la cabeza?
array++; hace que la matriz avance por sizeof (a_pointer) por lo que ahora ya no apunta a la dirección devuelta primero por realloc() . Eso significa que cualquier intento futuro de realloc() con la nueva dirección de la matriz dará como resultado el error "Puntero no válido, el puntero no se asignó inicialmente con la llamada a malloc, calloc o realloc" .
Además, si la array no se inicializa como NULL , entonces no puede usar realloc() para la asignación inicial. Inicializando n = 1; mezcla un conteo con un índice . Mantenga siempre el conteo para que sea el siguiente índice a llenar. Para 0 puede usar un if / else o ternary , por ejemplo
n = 0; ... if (n) { /* if n > 0 (not 1st allocation, use realloc) */ /* always realloc using a temporary pointer */ void *tmp = realloc (array, (n + 1) * sizeof *array); if (!tmp) { /* validate EVERY allocation */ /* handle error, return */ } array = tmp; /* assign reallocated block to array */ n += 1; /* increment count */ } else { /* initial allocation */ array = malloc (sizeof *array); if (!array) { /* validate EVERY allocation */ /* handle error, return */ } n += 1; /* increment count */ } /* rest of your strcpy here * VALIDATE strlen(token) > 0 AND < 50 */ /* note: you can consolidate both n += 1; here. duplicated for clarity */ Siempre llama a realloc() con un puntero temporal porque cuando (no si) realloc() falla, devuelve NULL , lo que sobrescribirá la dirección que apunta al bloque de memoria asignado creando una pérdida de memoria. por ejemplo, nunca hacer:
pointer = realloc (pointer, size); En cambio, al usar un puntero temporal, si falla realloc() , el pointer (su array ) aún apuntará al último bloque de memoria asignado y aún válido, lo que le permitirá usar lo que está almacenado allí Y le permitirá free() ese bloque de memoria cuando haya terminado con ella.
Tenga en cuenta que puede usar un ternario, pero es mucho menos legible:
Words *array = NULL; size_t n = 0; ... void *tmp = realloc (array, sizeof *array * n ? n + 1 : 1); if (!tmp) { /* validate EVERY allocation */ /* handle error, return */ } array = tmp; n += 1; /* rest of your strcpy here * VALIDATE strlen(token) > 0 AND < 50 */ En C, no hay necesidad de emitir el retorno de malloc (o calloc o realloc ), es innecesario. Ver: ¿Lanzo el resultado de malloc?