C free()调用中的指针无效

时间:2011-02-07 02:42:19

标签: c memory-management

我正在编写一个函数来使用正则表达式在字符串中查找变量。该功能工作正常,但是当我尝试释放保存我正在评估的字符串的临时char *时,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 个答案:

答案 0 :(得分:4)

您永远不会修改command_copy,但您正试图在command_copy-start处释放一个位置。

free(command_copy-start);行更改为free(command_copy);

从未输入循环时它起作用的原因,因为start永远不会从零变化。

答案 1 :(得分:1)

我在您的代码中看到了一些问题:

  1. 什么是command?使用sizeof(command)不会给字符串长度command;您需要mallocstrlen(command) + 1strcpy的{​​{1}}到command的缓冲区。

  2. Zooba关于command_copy的答复中的陈述。

答案 2 :(得分:1)

将来,您会考虑使用代码格式吗?只是编码风格的一个例子:

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 ++编写的。

答案 3 :(得分:0)

我还没有完成心理体操,但是使用调试器来运行这段代码应该是微不足道的。从malloc()返回什么地址,以及传递给free()的是什么?

另外,我认为将计算指针传递给free()是不好的形式。您应该传递从malloc()返回的相同值。如果需要,创建另一个变量。

答案 4 :(得分:0)

请注意,strncpy()不会表现出您认为相同的效果。如果源的字符串长度与目标中可用的字符数相同,则生成的字符串以null结尾。这几乎不是你想要的。

您可以通过执行以下操作来解决此问题:

     char* var_name = malloc((length + 1)*sizeof(char));
     strncpy(var_name, command_copy + start + pmatch.rm_so, length);
     var_name[length] = 0;