2011-02-07 81 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++編寫。