mallo c Неправильная ошибка контрольной суммы при попытке проанализировать ввод как токены - PullRequest
0 голосов
/ 10 марта 2020

Я пытаюсь создать оболочку, но продолжаю сталкиваться с ошибкой,

mallo c: неверная контрольная сумма для освобожденного объекта

в моем коде и также ошибки сегментации при тестировании, возможно ли исправить это? Я попытался отладить, но я не могу найти ничего необычного в коде, может кто-нибудь, пожалуйста, укажите мне правильное направление?

char **getArguments(char line[])
{
    /* Pointer to char pointer for storing arguments, initial size is 1 */
    char **args = malloc(sizeof(char *));
    /* Error handling */
    if (args == NULL)
    {
        fprintf(stderr, "Error: cannot split line.");
        exit(EXIT_FAILURE);
    }
    int count = 0;
    /* Try to parse first argument */
    char *temp = strtok(line, " \t\n\r\a");
    while (temp != NULL)
    {
        args[count] = temp;
        /* Reallocate more space for next argument */
        count++;
        char **reallocated = realloc(args, count * sizeof(char *));
        /* Error handling */
        if (reallocated == NULL)
        {
            fprintf(stderr, "Error: cannot split line.");
            exit(EXIT_FAILURE);
        }
        else
        {
            args = reallocated;
        }
        /* Move to next token */
        temp = strtok(NULL, " \t\n\r\a");
    }
    /* NULL terminate the array so that we know where's the end */
    args[count] = NULL;
    return args;
}

1 Ответ

1 голос
/ 10 марта 2020

Инициализация от count до 0, а затем присвоения с использованием args[count], кажется, проблема.

Функция getArguments() первоначально создает массив аргументов из одного элемента, но затем присваивает count = 0 - это должно быть 1, поскольку существует этот первый элемент.

Следующий код выполняет назначения с полной длиной count. Очевидно, что в C массивы индексируются от 0 до length-1, поэтому my_array[ length ] никогда не бывает корректным.

Простая инициализация count до 1 и исправление индексов массива для исправления со смещением 0 проблема.

/* Splits the command into arguments */
char **getArguments(char line[])
{
    /* Pointer to char pointer for storing arguments, initial size is 1 */
    char **args = malloc(sizeof(char *));
    /* Error handling */
    if (args == NULL)
    {
        fprintf(stderr, "Error: cannot split line.");
        exit(EXIT_FAILURE);
    }
    int count = 1;                                                       // <-- HERE
    /* Try to parse first argument */
    char *temp = strtok(line, " \t\n\r\a");
    while (temp != NULL)
    {
        args[count-1] = temp;                                            // <-- HERE
        /* Reallocate more space for next argument */
        count++;
        char **reallocated = realloc(args, count * sizeof(char *));
        /* Error handling */
        if (reallocated == NULL)
        {
            fprintf(stderr, "Error: cannot split line.");
            exit(EXIT_FAILURE);
        }
        else
        {
            args = reallocated;
        }
        /* Move to next token */
        temp = strtok(NULL, " \t\n\r\a");
    }
    /* NULL terminate the array so that we know where's the end */
    args[count-1] = NULL;                                           // <-- HERE
    return args;
}

Пример вывода (через Valgrind)

[user@machine]> valgrind ./run_cmds 
==8173== Memcheck, a memory error detector
==8173== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==8173== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==8173== Command: ./run_cmds
==8173== 
# /bin/echo foo
foo
# /bin/echo 1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# ==8173== 
==8173== HEAP SUMMARY:
==8173==     in use at exit: 120 bytes in 1 blocks
==8173==   total heap usage: 24 allocs, 23 frees, 3,544 bytes allocated
==8173== 
==8173== LEAK SUMMARY:
==8173==    definitely lost: 0 bytes in 0 blocks
==8173==    indirectly lost: 0 bytes in 0 blocks
==8173==      possibly lost: 0 bytes in 0 blocks
==8173==    still reachable: 120 bytes in 1 blocks
==8173==         suppressed: 0 bytes in 0 blocks
==8173== Rerun with --leak-check=full to see details of leaked memory
==8173== 
==8173== For lists of detected and suppressed errors, rerun with: -s
==8173== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Возможно, ваш код был направлен на использование realloc() в качестве присваивания или чего-то подобного, но более простым способом было бы просто посчитайте количество аргументов, выделите args для правильного размера (делается один раз), и, таким образом, не перераспределяйте l oop.

...