2011-02-07 44 views
0

我正在写一个函数来使用正则表达式在字符串中查找变量。该功能工作正常,但是当我尝试释放临时字符*,其中包含我正在评估的字符串时,glibc会调用一个无效的指针错误,程序将中止。在下面的代码中,如果while循环从未输入,则不会发生崩溃。C free()调用中的无效指针

我在做什么不正确?

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; 
} 

回答

4

你永远修改command_copy,但你试图在command_copy-start释放的位置。

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

当循环从未输入,因为start永远不会从零变为零。

1

我看到一对夫妇的问题,在您的代码:

  1. 什么是command?使用sizeof(command)将不会给出字符串长度command;你需要malloc缓冲区的大小为strlen(command) + 1strcpycommand到。

  2. Zooba的回答关于command_copy的说法。

+0

感谢您的更正。 – 2011-02-07 02:54:10

0

我没有做过心理体操弄明白,但它应该是微不足道的,通过使用调试器此代码运行。从malloc()返回什么地址,以及传递给free()的是什么?

此外,我认为这是一种糟糕的形式,将计算的指针传递给free()。您应该传递从malloc()返回的相同值。根据需要创建另一个变量。

0

请注意,strncpy()不会做你认为它确实做的事情。如果源的字符串长度与目标中可用的字符数相同,则结果字符串为而不是以空字符结尾。这几乎从来都不是你想要的。

您可以通过执行解决这个问题如下:

 char* var_name = malloc((length + 1)*sizeof(char)); 
    strncpy(var_name, command_copy + start + pmatch.rm_so, length); 
    var_name[length] = 0; 
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++ coverted到C.声明变量被用C++编写。