2012-10-25 57 views
0

我似乎無法找到與我正在做的事情完全匹配的問題,所以在這裏。下面是我的C應用程序的減少版本,直到問題出在哪裏。我知道這是醜陋的代碼,錯過了一些錯誤檢查,但它只是爲了解決這個問題。現在,下面的示例應該將所有'A'轉換爲BCDE。代碼中的評論描述了這個問題。 (邵仁枚首先執行)Realloc在傳遞指針上崩潰

int runMe2(char *in, char **buffer) { 
    long x; 
    long b_size = 0; 
    long i_size = 1000; 
    long i = 0; 
    char t_buffer[1006]; 

    // Initial malloc small as it will grow 
    *buffer = (char *)malloc(2*sizeof(char)); 
    strcpy(*buffer, ""); 
    for (x = 0; x < 999; x++) 
     t_buffer[x] = 0; 
    for (x = 0; x < strlen(in); x++) { 
     if (i >= i_size) { 
      char *r_buffer; 
      b_size = b_size + 1006*sizeof(char); 
      i_size = 0; 
      // Here is where the problem is. 
      // The first time through, i=1000, b_size=1006 and everything is fine 
      // The second time throgh, i=1004, b_size=2012 and the heap crashes on the realloc 
      r_buffer = (char *)realloc(*buffer, b_size); 
      if (r_buffer == NULL) 
       exit(0); 
      *buffer = r_buffer; 
      strcat(*buffer, t_buffer); 
      for (x = 0; x < 999; x++) 
       t_buffer[x] = 0; 
     } 
     if (in[x] == 'A') { 
      t_buffer[i++] = 'B'; 
      t_buffer[i++] = 'C'; 
      t_buffer[i++] = 'D'; 
      t_buffer[i++] = 'E'; 
     } 
    } 
} 

int runMe() { 
    char *out; 
    char in[30000]; 
    int x = 0; 

    // Set up a 29,999 character string 
    for (x = 0; x < 30000; x++) 
     in[x] = 'A'; 
    in[29999] = 0; 
    // Send it as pointer so we can do other things here 
    runMe2(in, &out); 
    // Eventually, other things will happen here 
    free(out); 
} 
+1

你的意思是傷害'x',爲什麼不只是'memset' ? '''不會''t_buffer'結束? – Useless

+0

什麼是一段難看的代碼;你正在做很多不需要的操作,並且你正在使用不真正需要的「幫助」值的人 – codewarrior

+0

我不知道你認爲*做了什麼,但是從我所能看到的情況來看,它將BCDE連接到t_buffer中,在put字符串中,最終將緩衝區轉儲到增長目標*所有其他字符!='A'都是LOST。*如果這是故意的,有很多*更容易的方法來做到這一點,但有些事情告訴我,即使你崩潰'固定'這段代碼不會做你認爲它會。 – WhozCraig

回答

3
if (i >= i_size) { 
    ... 
    i_size = 0; 
    ... 
} 
if (in[x] == 'A') { 
    t_buffer[i++] = 'B'; 
    ... 

這不可能是正確的。如果in長於原始的i_size,那麼您將在t_buffer的末尾寫入。您可能打算在那裏重置i,而不是i_size

然後,如果您不能確保它正確地以null結尾,則您使用的字符串函數爲t_buffer - 您初始化第一千個值,但會覆蓋循環中的那些值。如果你打算使用strcat和朋友,你需要更加小心,以確保它保持空終止。但使用memcpy會導致更簡單的代碼,因爲您知道所涉及陣列的長度。

for (x = 0; x < strlen(in); x++) { 
    ... 
    for (x = 0; x < 999; x++) 
    ... 
    t_buffer[x] = 0; 

這不可能是正確的或者由Useless的發現。爲此使用第二個變量,或者更好地使用memset

2

只是爲了好玩這裏有一個不同的算法中的作品,是比你的要簡單得多:當你的realloc後重置`t_buffer`

int runMe2(char *in, char **buffer) 
{ 
    // Count number of A's 
    int number_of_As = 0; 
    int i, j; 
    for (i = 0; 0 != in[i]; i++) { 
     if (in[i] == 'A') { 
      number_of_As += 1; 
     } 
    } 

    // If number_of_As == 0, you can just do a strdup here and return 

    // Because of 1st loop, i == strlen(in), no need to call strlen 
    long bytes = (i - number_of_As + (number_of_As * 4) + 1) * sizeof(char); 
    // Error check here 

    // Only 1 memeory allocation needed 
    *buffer = (char *)malloc(bytes); 

    // Simple copy loop 
    for (i = 0, j = 0; 0 != in[i]; i++) { 
      // If it's an A replace 
     if (in[i] == 'A') { 
      (*buffer)[j++] = 'B'; 
      (*buffer)[j++] = 'C'; 
      (*buffer)[j++] = 'D'; 
      (*buffer)[j++] = 'E'; 
     } 
      // Not an A, just copy 
     else { 
      (*buffer)[j++] = in[i]; 
     } 
    } 
    // Null terminate 
    (*buffer)[j] = 0; 

    return j; 
} 
+0

+1:我完全喜歡這個答案。但是,字節計算的因素。 '-number_of_As +(number_of_As * 4)'就是(number_of_As * 3)。 = P – WhozCraig