2012-09-26 321 views
1
struct TokenizerT_ { 
    char* separators; 
    char* tks; 
    char* cur_pos; 
    char* next; 
    }; 

    typedef struct TokenizerT_ TokenizerT; 

    TokenizerT *TKCreate(char *separators, char *ts) 
    { 
    TokenizerT *tokenizer; 
    tokenizer = (TokenizerT*)malloc(sizeof(TokenizerT)); 

    //some manipulation here 

    tokenizer->tks = (char*) malloc (strlen(str)* sizeof(char)); 
    tokenizer->tks=str; 
    printf("size of tokenizer->tks is %zu\n", strlen(tokenizer->tks)); //this prints out the correct number (e.g. 7) 
    return tokenizer; 
    } 

    int main(int argc, char **argv) 
    { 
    TokenizerT *tk = TKCreate(argv[1], argv[2]); 
    printf("tk->tks: %zu\n", strlen(tk->tks)); //HOWEVER, this prints out the wrong number (e.g. 1) 
    } 

從上面的代碼可以看出,我正在使用指向結構體的指針。出於某種原因,我沒有收到tk-> tks的正確長度。我無法理解這一點,因爲它應該與TKCreate函數中tks的大小相同。有人可以解釋這個嗎?指向c中的結構的指針

回答

2

我懷疑你的代碼片段中沒有顯示其定義的str是TKCreate()中定義的局部變量。如果是這樣的話,你將tokenizer-> tks賦值爲str,它指向TKCreate()範圍內的一個適當的字符串,但是在退出TKCreate()時,釋放棧內容(包括參數和局部變量)並且當你試圖引用TKCreate()範圍之外的指針時,所有投注都關閉。

一個合理的修復方法是動態地爲tokenizer-> tks分配存儲空間,因此它在退出TKCreate()後仍然存在。我看到你通過調用malloc來做到這一點,但是你用str從一個明確的賦值來覆蓋它。相反,你應該通過strcpy(tokenizer-> tks,s​​tr)將str的內容(使用strcpy)複製到動態分配的內存中。

+0

你是對的。我怎樣才能解決這個問題? – user1363410

+0

我剛剛添加了第二段來解釋此修復程序。看看是否有幫助。 –

0

你應該strcpystr的內容tokenizer->tks,因爲當你使用賦值運算符,你失去的指針malloc給你,創造了內存泄漏,指着tokenizer->tks一個局部變量,這將在之後被銷燬函數的返回。

因此,辦法是這樣的:

tokenizer->tks = (char *)malloc ((strlen(str) + 1) * sizeof(char)); 
strcpy(tokenizer->tks, str); 

另一件事:

您免費tk本身之前,不要忘了free->tks

因此,printf的之後,你應該使用:

free(tk->tks); 
free(tk); 

有未釋放的結構和字符串(這是另一個存儲位置,而不是結構的存儲空間內沒問題,這就是爲什麼你必須釋放它們兩者),如果你的程序很小,因爲它執行後,程序的內存將被消除。但是如果你打算在一個全面工作的大計劃中實現這個功能,釋放內存是一個很好的行爲。

+0

'strlen(str)+ 1',請! –

+0

@JonathanLeffler很好! –

0

不清楚str是在哪裏定義的,但如果它是函數中的局部變量,那麼問題很可能是它超出了範圍,因此數據被覆蓋。

你的內存泄漏,因爲你忘了使用strcpy()memcpy()memmove()的值str在所分配的空間複製,你覆蓋只指向新分配的內存指針str。如果你複製了,你會寫出界限,因爲你忘記爲尾部null和字符串分配足夠的空間。您還應該檢查分配是否成功。

虛假碼:

tokenizer->tks = (char*) malloc (strlen(str)* sizeof(char)); 
tokenizer->tks = str; 

固定碼:

size_t len = strlen(str) + 1; 
tokenizer->tks = (char *)malloc(len); 
if (tokenizer->tks == 0) 
    ...error handling... 
memmove(tokenizer->tks, str, len); 

使用memmove()memcpy()可以超越strcpy()得心應手(參見Why is Python faster than C一些插圖和定時)。有些人會因爲在malloc()上使用演員而使你(和我)我明白他們爲什麼會這樣爭論,但我並不完全同意他們(通常我自己也會使用演員)。由於sizeof(char)的定義是1,所以沒有特別需要乘以它,儘管這樣做也沒有損害。