2012-04-25 63 views
1

我有以下的方案,其中嘗試來標記串(基於空間),並將其寫入到一個char **陣列。斷言在malloc.c:2453

#include <stdio.h> 
#include <stdlib.h> 

#define len 180 

void tokenize(char *str, char **tokens) 
{ 
    int l = 0, index = 0; 
    int i = 0; 
    int str_i; 
    int tok_i; 

    while(*str) { 
     if (*str == ' ') { 
      tokens[i] = malloc(sizeof(char) * l+1); 
      if (tokens[i] == NULL) return; 

      tok_i = 0;   
      for (str_i=index-len ; str_i<index ; str_i++) { 
       tokens[i][tok_i] = str[str_i]; 
       tok_i++; 
      } 

      tokens[i][tok_i] = '\0'; 
      tokens[i++] = NULL; 
      l = 0; 
      index++; 
     } 
     str++; 
     l++; 
     index++; 
    }  

    return;   
} 

int main() 
{ 
    char str[len] = "this is a test string"; 
    char **tokens = malloc(100 * sizeof(char *)); 

    if (str == NULL || tokens == NULL) 
     return 1; 

    printf("input string: %s\n", str); 
    tokenize(str, tokens); 

    return 0; 
} 

上述程序編譯罰款,但在執行的時候,我在malloc.c

$ gcc -ggdb -Wall prog.c 
$ ./a.out 
input string: this is a test string 
a.out: malloc.c:2453: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed. 
Aborted (core dumped) 
$ 

得到了下面的聲明,然後將堆棧跟蹤顯示以下內容:

(gdb) bt 
#0 0x0000003b28036285 in raise() from /lib64/libc.so.6 
#1 0x0000003b28037b9b in abort() from /lib64/libc.so.6 
#2 0x0000003b2807d37d in __malloc_assert() from /lib64/libc.so.6 
#3 0x0000003b28080c37 in _int_malloc() from /lib64/libc.so.6 
#4 0x0000003b28082595 in malloc() from /lib64/libc.so.6 
#5 0x000000000040055f in tokenize (str=0x7fffffffe017 " a test string", tokens=0x601010) at prog.c:15 
#6 0x00000000004006de in main() at prog.c:46 
(gdb) 

如何調試這個?任何想法將不勝感激。

+0

爲什麼不直接使用strtok的? – 2012-04-25 03:52:51

+0

我的C太生疏給你任何有用的意見,而不坐在這裏盯着它20分鐘,但我可以立即告訴你,你忘了你的自由令牌的指針,因此,該程序泄漏內存(儘管不是很很多),因爲大概這是一個家庭作業(否則你真的應該只使用strtok),這會花費你點。 :) – 2012-04-25 03:57:23

回答

3

在你的for循環

for (str_i=index-len ; str_i<index ; str_i++) 

STR_I是負數。

3
for (str_i=index-len ; str_i<index ; str_i++) { 
     tokens[i][tok_i] = str[str_i]; 
     tok_i++; 
} 

tokens[i][tok_i] = '\0'; 

至少那些tokens[i][tok_i]之一是分配的內存所以你最終重挫malloc的內部信息之外。之後,hilarity ensues

str_i初始化也很有趣,因爲這將是-180對於第一次迭代。

1

是,從@cnicutar和@spicavigo建議,我改變了代碼如下所示,工作正常。

#include <stdio.h> 
#include <stdlib.h> 

#define str_len 180 

void tokenize(char *str, char **tokens) 
{ 
    int length = 0, index = 0; 
    int i = 0; 
    int str_i; 
    int tok_i; 

    while(str[length]) { 
     if (str[length] == ' ') { 
      /* this charecter is a space, so skip it! */ 
      length++; 
      index++; 

      tokens[i] = malloc(sizeof(char) * (index+1)); 

      tok_i = 0;   
      for (str_i=length-index ; str_i<length; str_i++) { 
       tokens[i][tok_i] = str[str_i]; 
       tok_i++; 
      } 

      tokens[i][tok_i] = '\0'; 
      i++; 
      index = 0; 
     } 
     length++; 
     index++; 
    }  

    /* copy the last word in the string */ 
    tokens[i] = malloc(sizeof(char) * index); 
    tok_i = 0;   
    for (str_i=length-index ; str_i<length; str_i++) { 
     tokens[i][tok_i] = str[str_i]; 
     tok_i++; 
    } 
    tokens[i][tok_i] = '\0'; 
    tokens[i++] = NULL; 

    return;   
} 

int main() 
{ 
    char *str = malloc(str_len * sizeof(char)); 
    char **tokens = malloc(100 * sizeof(char *)); 
    int i = 0; 

    if (str == NULL || tokens == NULL) 
     return 1; 

    gets(str); 
    printf("input string: %s\n", str); 
    tokenize(str, tokens); 

    while(tokens[i] != NULL) { 
     printf("%d - %s \n", i, tokens[i]); 
     i++; 
    } 

    while(tokens[i]) 
     free(tokens[i]); 
    free(tokens); 
    free(str); 

    return 0; 
} 
+0

它可能工作,但'令牌[I] = malloc的(的sizeof(char)的*索引);'不分配足夠的存儲器,行'令牌[I] [tok_i] = '\ 0';'將總是緩衝區溢出。例如,當索引爲1且長度爲1時,它將malloc 1個字節,複製一個字節,然後將'\ 0'寫入'tokens [i] [1]' – weston 2012-04-25 08:22:10

+0

'索引'和'長度' ,這使得難以遵循。 'index'是一個不是空格的記號count,'length'是源數組中的'index'。 – weston 2012-04-25 08:25:46

+0

@weston'malloc'上的好點。我糾正了相同的情況。 – 2012-04-25 08:26:33