调用strtok()后释放内存会导致错误

时间:2016-01-13 08:42:58

标签: c malloc 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);
    
  5. 该代码存在我无法free(filename)的问题。如果我尝试free(filename),请编程获取SIGTRAP。但是计划正在发挥作用。

    我想解决这个问题。我该怎么办?

4 个答案:

答案 0 :(得分: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) { ... }

答案 1 :(得分:2)

使用strtok()

时,无需分配内存

释放文件名没有问题,因为 malloc()正确分配了文件,但是还有许多其他问题和内存泄漏。 基本上你首先为 str_ptr

分配内存
strk_ptr = malloc(sizeof(filename));

此处 malloc()返回存储在 strk_ptr 中的指针。 然后你调用 strtok(),它还会在文件名中返回一个指针:

strk_ptr = strtok(filename,".");

所以你丢失了 malloc()返回的原始指针,现在 strk_ptr 指向 filename 中的某个位置。当您致电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)返回指针的大小而不是内容的大小,因为 filename 不是数组。你必须使用strlen(filename) + 1

strtok 在已分配的对象(文件名)内返回一个指针,这样不需要分配内存> strk_ptr

在循环中使用strtok时,请考虑采用以下方法:

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

答案 2 :(得分:1)

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

strk_ptr得到一些内存,你可以通过将strk_ptr指向文件名内存来留下悬空,然后最终双重释放文件名。

所以不要malloc strk_ptr。只需将其保留为char *,然后只留下最后的免费文件名

答案 3 :(得分:0)

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

不起作用。首先,strk_ptr指向malloc的内存,但是指针会立即被其他一些值覆盖,所以基本上你失去了指向malloc内存的指针,因此不能{{1}那个记忆了。

编辑:

看到free,我应该补充一点,必须为指针变量本身分配内存。声明malloc(sizeof(filename))使编译器隐式地为该指针分配内存(即4或8个字节)。所以你可以像任何其他变量一样直接使用指针,你不必char* strk_ptr;那个变量的记忆。

free

或者,如果那不是你的意图,那么请注意char* strk_ptr; strk_ptr = strtok(filename,"."); 返回字符串的长度,而只返回指针变量{{1}的大小},即通常为4或8,与字符串sizeof(filename)指向的无关。另请参阅http://www.gnu.org/software/libc/manual/html_node/String-Length.html

filename