C Неверный указатель в вызове free () - PullRequest
0 голосов
/ 07 февраля 2011

Я пишу функцию для поиска переменных в строке с помощью регулярного выражения.Эта функциональность работает нормально, но когда я пытаюсь освободить временный символ *, содержащий строку, которую я оцениваю, glibc вызывает ошибку неверного указателя, и программа прерывается.В приведенном ниже коде, если цикл while никогда не вводится, сбой не происходит.

Что я делаю неправильно?

int parse_variables(size_t read_len)
{
    regex_t comp_regex;
    int start = 0;
    char *command_copy = malloc(sizeof(command));
    strcpy(command_copy, command);
    if (regcomp(&comp_regex, "[$][^0-9_][A-Z0-9_]+", REG_EXTENDED) != 0)
    {
        pmesg(1, "Regex compilation failed. Not parsing for variables.\n");
        return -1;
    }
    regmatch_t pmatch;
    int var_match = regexec(&comp_regex, command_copy+start, comp_regex.re_nsub+1, &pmatch, 0);
    pmesg(1, "The initial value of var_match is %i.\n", var_match);
    while (var_match == 0) // We are finding instances matching the regex
    {
        int length = pmatch.rm_eo-pmatch.rm_so;
        char* var_name = malloc(length*sizeof(char));
        strncpy(var_name, command_copy + start + pmatch.rm_so, length);
        pmesg(1, "The length is: %i - %i = %i.\n", pmatch.rm_eo, pmatch.rm_so, length);
        pmesg(1, "The variable's name is: %s.\n", var_name);
        free(var_name);
        start += pmatch.rm_eo;
        var_match = regexec(&comp_regex, command_copy+start, comp_regex.re_nsub+1, &pmatch, 0);
    }
    free(command_copy-start);
    return 0;
}

Ответы [ 5 ]

4 голосов
/ 07 февраля 2011

Вы никогда не изменяете command_copy, но пытаетесь освободить место в command_copy-start.

Измените строку free(command_copy-start); на free(command_copy);.

Причина, по которой это работает, когда цикл никогда не вводится, потому что start никогда не меняется с нуля.

1 голос
/ 07 февраля 2011

В будущем, вы бы хотели использовать форматирование кода?Только один пример стиля кодирования:

int parse_variables(size_t read_len)
{
    regex_t         comp_regex;
    regmatch_t      pmatch;
    int             start = 0;
    char*           command_copy;
    int             var_match;
    Some_result_t   regcomp_result;

    command_copy = malloc(sizeof(command));
    strcpy(command_copy, command);

    regcomp_result = regcomp (&comp_regex,               /* <description of what this parameter does> */
                              "[$][^0-9_][A-Z0-9_]+",    /* <description of what this parameter does> */
                              REG_EXTENDED);             /* <description of what this parameter does> */

    if (regcomp_result != 0 )
    {
        pmesg(1, "Regex compilation failed. Not parsing for variables.\n");
        return -1;
    }

    var_match = regexec (&comp_regex,                    /* <description of what this parameter does> */
                         command_copy + start,           /* <description of what this parameter does> */
                         comp_regex.re_nsub + 1,         /* <description of what this parameter does> */
                         &pmatch,                        /* <description of what this parameter does> */
                         0);                             /* <description of what this parameter does> */

    pmesg (1,
           "The initial value of var_match is %i.\n",
           var_match);

    while (var_match == 0) // We are finding instances matching the regex
    {
        int    length;
        char*  var_name;

        length = pmatch.rm_eo-pmatch.rm_so;
        var_name = malloc(length * sizeof(char));

        strncpy (var_name,
                 command_copy + start + pmatch.rm_so,
                 length);

        pmesg (1,
               "The length is: %i - %i = %i.\n",
               pmatch.rm_eo,
               pmatch.rm_so,
               length);

        pmesg (1,
               "The variable's name is: %s.\n",
               var_name);

        free(var_name);
        start += pmatch.rm_eo;

        var_match = regexec (&comp_regex,
                             command_copy+start,
                             comp_regex.re_nsub+1,
                             &pmatch,
                             0);

    } /* while (var_match == 0) */

    free(command_copy-start);
    return 0;
}

Помимо стиля кода, функциональность кода идентична оригиналу, хотя и покрыта от C ++ до C. Объявления переменных написаны на C ++.

1 голос
/ 07 февраля 2011

Я вижу пару проблем в вашем коде:

  1. Что такое command?Использование sizeof(command) не даст длину строки command;вам нужно malloc буфер размером strlen(command) + 1 до strcpy с command в.

  2. Утверждение в ответе Zooba о command_copy.

0 голосов
/ 07 февраля 2011

Обратите внимание, что strncpy() не делает то, во что вы, кажется, верите.Если длина строки источника равна количеству символов, доступных в месте назначения, тогда результирующая строка будет иметь значение , а не с нулевым символом в конце.Это почти никогда не то, что вы хотите.

Это можно исправить, выполнив следующие действия:

     char* var_name = malloc((length + 1)*sizeof(char));
     strncpy(var_name, command_copy + start + pmatch.rm_so, length);
     var_name[length] = 0;
0 голосов
/ 07 февраля 2011

Я не занимался умственной гимнастикой, чтобы понять это, но бегать по этому коду с помощью отладчика должно быть тривиально. Какой адрес возвращается из malloc (), а какой передается free ()?

Кроме того, я считаю плохой формой передавать вычисленный указатель в free (). Вы должны передать то же значение, которое было возвращено из malloc (). При необходимости создайте другую переменную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...