Problemas de reasignación cuando se asigna una cadena a una matriz int dinámica

Básicamente, estoy tratando de convertir un montón de entradas de char en ints y asignarlas a una matriz int dinámica. La entrada de cadena y la tokenización parecen funcionar bien. El problema (por lo que puedo decir) parece ser la reasignación de la matriz int; una vez reasignada la matriz dos veces, el puntero a la matriz int devuelve NULL .

Lo que intenté hacer fue duplicar el tamaño de la matriz int cada vez que el número de tokens alcanza o supera (tamaño dividido por sizeof (int)). La instrucción realloc funciona cada vez que se cumple esta condición.

Pensé que usar un puntero a un puntero era la solución final para esto. Apuesto a que es un problema realmente obvio, pero estoy en mi punto final aquí. Si solicita más elaboración, haré mi mejor esfuerzo. Entiendo que solo he tomado C por un semestre y he luchado la mayor parte del camino.

Además, a decir verdad, esto era parte de una tarea de clase que ya pasó. Preferiría una explicación sobre lo que está mal más que un código completo, si eso está bien.

Tengo muchas declaraciones de printf, así que me disculpo por cualquier desorden.

EDIT: reemplazó todas las instancias de newArray dentro de la función input() con * resize. Sin embargo, nunca he intentado asignar valores a través de punteros a punteros, así que siéntete libre de corregirme con un ejemplo sintáctico si sabes cómo me equivoqué. La falla de segmentación ocurre aquí:

for (k = (numElem - count); k < numElem; k++)
{
    printf("\nk = %i\n", k);
    printf("j = %i\n", j);
    printf("numElem = %i\n", numElem);
    printf("results[j]: %s\n\n\n", results[j]);

    /* Segmentation fault regardless of what is assigned
    to *resize[k]. */
    *resize[k] = atoi(results[j]);//PROBLEM HERE
    j++;
}

El código fuente ha sido actualizado para reflejar esto. Para hacer que esta publicación ridículamente larga sea un poco más moderada, digamos que hice esto en main ():

    int *newArray = malloc(MAXTOKEN * sizeof(int));

    input(&newArray);  

    free(newArray);  

Continuando.

/* String input takes in char values,
tokenizes them, converts the results
to int, assigns them to newresizeay. */
int input(int **resize)
{
    int i, j, k, count;

    int numElem = 0;
    int currentSize = MAXTOKEN;

    char str[MAXSTRING];
    char *results[MAXTOKEN];

    /* This entire loop takes place at least once,
    provided the first input isn't NULL. */
    do
    {     
        i = 0, j = 0, k = 0;

        /* Char input process. Takes place until the user
        presses ENTER. */
        printf("Input integer values separated by spaces, or "
            "press ENTER to exit.\n");   
        while ( ((str[i] = getchar() ) != '\n') && (i < MAXSTRING) )
            i++;
        printf("\n\n");

        str[i] = '\0';


        /* Tokenization of the chars that were input */
        count = 0;

        if (results[0] = strtok(str, " \t"))
            count++;

        while (results[count] = strtok(NULL, " \t") )
            count++;


        /* numElem = 1 if the first input prompt established
        str[0] as NULL */
        if ( (count < 1) && (numElem < 1) )    
            count = 1;

        numElem += count;

        printf("numElem: %i\ncurrentSize: %i\n", numElem, currentSize);

        /* If the number of elements to assign meet or surpass
        the amount of [memory/sizeof(int)], exponentially
        increase the size of the int resizeay. */
        if ( numElem >= currentSize )
        { 
            *resize = realloc(*resize, (currentSize) * sizeof(int));
            if (*resize == NULL)
                printf("\n\nYep, it threw up.\n\n");
            currentSize *= 2;
        }


        printf("\nSize should be: %i\n", currentSize * 4);
        printf("Actual size: %d\n", _msize(*resize));


        /* The tokenized chars are converted to integers and
        assigned to the int resizeay. */
        for (k = (numElem - count); k < numElem; k++)
        {
            printf("\nk = %i\n", k);
            printf("j = %i\n", j);
            printf("numElem = %i\n", numElem);
            printf("results[j]: %s\n\n\n", results[j]);

            *resize[k] = atoi(results[j]);//PROBLEM HERE
            j++;
        }

        for (i = 0; i < numElem; i++)
            printf("resize[%i]: %i\n", i, *resize[i]);               

        printf("\n\n\n");      

    } while (str[0] != NULL);   

}
0
No he investigado esto en profundidad, pero parece un problema de corrupción.
agregado el autor Jabberwocky, fuente

3 Respuestas

Entre otros problemas:

char *results[MAXTOKEN];

debiera ser

char *results[MAXTOKEN + 1];

porque aquí el valor máximo de conteo será MAXTOKEN en este ciclo:

while (results[count] = strtok(NULL, " \t") )
  count++;

y

char str[MAXSTRING];

es bastante aterrador, porque tan pronto como el usuario ingrese más de MAXSTRIN (= 11) caracteres sin presionar Enter, obtendrá un desbordamiento del búfer.

0
agregado

La función de entrada recibe tanto resize como arr . main envía el mismo puntero a ambos. Este es un error.

Cuando se cambia el tamaño de resize , arr se mantiene igual y puede apuntar a una dirección no válida (cuando realloc devuelve una dirección diferente).

Como arreglar: Elimine el argumento de función arr y solo use resize .

0
agregado
Entonces, ¿tendría que asignar los valores atoi como * resize [i] = atoi (results [j])? Cuando hice esto, el primer valor de la nueva matriz int apareció muy bien, pero las entradas consecutivas se bloquean una vez que se intenta la asignación en el índice consecutivo. Editaré mi publicación en breve.
agregado el autor user3109954, fuente
Debería decir más profesionalmente: hice exactamente lo que sugirió y todo funciona a la perfección. Decir que estoy agradecido es una subestimación. Estaba obsesionado con esto, y ahora puedo descansar.
agregado el autor user3109954, fuente
Use (* cambio de tamaño) [i].
agregado el autor egur, fuente
También puede declarar int * arr = * resize; y trabajar con eso. Solo actualiza el tamaño antes de regresar. realloc funcionará en arr .
agregado el autor egur, fuente

Cuando llame a la función realloc, si el nuevo bloque de memoria es más pequeño que el anterior, mantendrá el estado original apuntando al bloque de memoria que utilizó anteriormente. Si el nuevo bloque de memoria es más grande que el anterior, el sistema volverá a asignar memoria en el montón y la memoria anterior se libera.

0
agregado