2016-01-13 161 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); 
    } 
相关问题