2016-01-13 43 views
4

您能幫我嗎?我的代碼不符號化,所以我創造了這樣的代碼:調用strtok()後釋放內存會導致錯誤

  1. 我分配一些內存,
  2. strcpy(malloced_memory, argv)
  3. 我執行strtok(mallocted_memory, ".")
  4. 嘗試free(mallocted_memory)

    filename = malloc(strlen(argv)); 
    
    strcpy(filename, argv); 
    strk_ptr = malloc(sizeof(filename)); 
    strk_ptr = strtok(filename,".");// 
    i++; 
    sprintf(in->file_name,"%s",strk_ptr); 
    
    while(strk_ptr = strtok(NULL,"."))// 
    { 
        i++; 
        sprintf(in->file_name,"%s.%s",in->file_name,strk_ptr); 
        sprintf(in->file_ext ,"%s",strk_ptr); 
    } 
    free(strk_ptr); 
    free(filename); 
    

該代碼有問題,我不能free(filename)。如果我嘗試free(filename),則程序獲得SIGTRAP。但程序正在工作。

我想解決這個問題。我該怎麼辦?

回答

1
filename = malloc(strlen(argv)); 
strk_ptr = malloc(sizeof(filename)); 

strk_ptr得到了一些記憶,你然後再離開通過指向strk_ptr到文件名存儲晃來晃去,然後你最終雙釋放文件名。

所以不要malloc strk_ptr。剛剛離開它爲char *然後只免費文件名在最後

3

這條線:

filename = malloc(sizeof(argv)); 

應該是這樣的:

filename = malloc(strlen(argv) + 1);  /* +1 for the '\0' at the end */ 
if (filename == NULL) { /* take some action */ } 

這行:

strk_ptr = malloc(sizeof(filename)); 

是隻是因爲它跟隨而造成內存泄漏:

strk_ptr = strtok(filename,"."); 

你應該檢查返回值:

strk_ptr = strtok(filename,"."); 
if (strk_ptr == NULL) { /* take some action */ } 

順便說一句,在strtok()功能(在你的例子filename)返回一個指向初始調用傳遞給它的字符串中的令牌。它不分配內存,所以它的返回值不應該被釋放(這是你的程序避免的,但這是一個常見的錯誤)。雖然我在暗示strtok(),但我會提到你不能(直接或間接地)將字符串傳遞給tokenize,因爲它修改了字符串,並且字符串是隻讀的。就是這樣做:strtok("sample.txt", ".")是不行的。

最後,這種隱含的條件是不是很大形式:

while (strk_ptr = strtok(NULL,".")) { ... } 

更好的是:

while ((strk_ptr = strtok(NULL,".")) != NULL) { ... } 
+0

他們沒有問釋放strtok的記憶,他們詢問使用的strtok後釋放他們的記憶。 –

+0

@KeithNicholas謝謝,重寫了一下 –

0
strk_ptr = malloc(sizeof(filename)); 
strk_ptr = strtok(filename,".");// 
... 
free(strk_ptr); 

不工作。起初,strk_ptr指向malloc'd內存,但隨後指針立即被其他值覆蓋,所以基本上你會失去指向malloc'd內存的指針,因此不能再使用該內存。

編輯:

看到malloc(sizeof(filename)),我要補充一點,你必須爲指針變量本身分配內存。聲明char* strk_ptr;使編譯器爲該指針隱式分配內存(即4或8字節)。因此,您可以直接像使用其他變量一樣使用指針,並且不需要free該變量的內存。

char* strk_ptr; 
strk_ptr = strtok(filename,"."); 

或者,如果這不是你的意圖,然後注意sizeof(filename)返回字符串的長度,但指針變量filename的只是大小,即通常是4或8,獨立的什麼字符串filename指向。也http://www.gnu.org/software/libc/manual/html_node/String-Length.html參見:

char string[32] = "hello, world"; 
char *ptr = string; 
sizeof (string) 
    ⇒ 32 
sizeof (ptr) 
    ⇒ 4 /* (on a machine with 4 byte pointers) */ 
+0

@JohnHascall是的,你是對的。 – JimmyB

2

你不需要使用的strtok()

有在釋放,因爲它是通過正確的malloc 分配沒有問題的時候分配內存()但是還有很多其他問題和內存泄漏。 基本上你首先爲str_ptr分配內存:

strk_ptr = malloc(sizeof(filename)); 

這裏的malloc()返回其被存儲在strk_ptr的指針。 然後調用的strtok()也返回一個指針,內部

strk_ptr = strtok(filename,"."); 

所以你在丟失)通過的malloc(返回原來的指針現在strk_ptr地方點文件名。當您撥打free(str_ptr)時,您可以釋放文件名中的內存。隨後致電free(filename)報告錯誤。解決方法就是不需要爲strk_ptr分配內存。

我寫了一個工作最小代碼,向您展示如何正確使用strtok。請記住,在提問時,發佈最低工作代碼總是更好。

int main(int argc, char **argv) { 

    char *strk_ptr; 
    char *filename = malloc(strlen(argv[0]) + 1); 

    strcpy(filename, argv[0]); 

    printf("filename = %s, size = %zu\n", filename, sizeof(filename)); 

    // Do not malloc this 
    //strk_ptr = malloc(strlen(filename) + 1); 
    strk_ptr = strtok(filename,".");// 
    printf("%s\n", strk_ptr); 

    while((strk_ptr = strtok(NULL,"."))) 
    { 
     printf("%s\n", strk_ptr); 
    } 
    free(filename); 

    return 0; 
} 

所有的argv首先是一個char **,所以如果你想作爲輸入傳遞,你必須使用argv的第一個參數的內容複製[0],這始終是可執行文件名稱。

然後,sizeof(filename)返回指針的大小而不是內容的大小文件名不是數組。你必須使用strlen(filename) + 1

的strtok返回一個指針,它已經被分配,所以你不需要strk_ptr分配內存中的對象()內。

當使用一個循環的strtok考慮採取以下做法:

for (strk_ptr = strtok(filename, "."); strk_ptr; strk_ptr = strtok(NULL, ".")) 
    { 
     printf("%s\n", strk_ptr); 
    }