如何在C中正确使用strtok,以便没有内存泄漏?

时间:2011-02-15 05:42:41

标签: c malloc free strtok

当你在C中的一个char指针上调用strtok时会发生什么让我感到困惑。我知道它会修改字符串的内容,所以如果我在一个名为'line'的变量上调用strtok,它的内容就会改变。假设我遵循以下方法:

void function myFunc(char* line) {

    // get a pointer to the original memory block
    char* garbageLine = line;

    // Do some work
    // Call strtok on 'line' multiple times until it returns NULL
    // Do more work

    free(garbageLine);
}

进一步假设'line'在传递给myFunc之前被malloced。我应该在使用strtok之后释放原始字符串还是为我们完成工作?另外,如果'line'没有被malloced并且我尝试使用上面的函数会发生什么?取而代之的是更安全吗? (假设程序员不知道该行未被malloced,则不会免费拨打电话)

调用

char* garbageLine = line;
myFunc(line);
free(garbageLine);

功能定义

void function myFunc(char* line) {
    // Do some work
    // Call strtok on 'line' multiple times until it returns NULL
    // Do more work
}

5 个答案:

答案 0 :(得分:9)

strtok()不会释放任何内容,因为它不知道字符串的存储位置。它可能在堆栈或堆上,它不知道或关心! :)

  

执行以下操作会更安全吗?

你的第二个例子要好得多,因为它简化了myFunc(),并且在更多情况下使它很有用,因为函数不需要知道字符串的分配位置。通过从myFunc()中删除对free()的调用,您可以使用该函数来解析堆栈或堆中的字符串。调用者分配内存,调用者释放内存!

进一步阅读: strtok()

答案 1 :(得分:4)

在你的问题的评论中,你说你“多次在'线'上调用strtok直到它返回NULL”。这听起来好像你可能错误地使用了strtok。第一次调用它时,你应该用'line'作为参数调用它;在后续调用中,您应该将其传递为NULL。以下面的例子为例:

void function myFunc(char* line) {
  char *segment; // This will point at each delimited substring in turn.

  segment = strtok(line, " ");

  // Do something with segment.

  segment = strtok(NULL, " ");

  // Do something with the new segment.

  free(line);
}

正如DrTwox所说,你的第二个例子更好 - 'line'应该被malloced(或不是)的相同上下文释放,所以对free()的调用不属于这个函数。你最好还是循环它 - 比如:

void function myFunc(char* line) {
  char *segment;

  segment = strtok(line, " ");

  while (segment != NULL) {
    // Do something with segment.

    segment = strtok(NULL, " ");
  }
}

调用是这样的:

char *line = malloc(20*sizeof(char));

// Check that malloc succeeded here.
// Put some data into 'line'.

myFunc(line);

free(line);

// No 'garbageLine' required.

strtok的工作方式有点复杂,但你有重要的部分 - 它没有分配或释放任何记忆。相反,它通过修改传递给它的字符串来工作。

答案 2 :(得分:1)

strtok没有比strlen更能释放内存了。你为什么期望它?它会释放什么记忆?也许你认为strtok需要释放内存,因为它存储了一个NUL,但内存的内容是无关紧要的。分配内存时,分配器会跟踪您分配的块的大小,并在释放时释放整个块。

答案 3 :(得分:1)

值得解释的是strtok通过以下方式来完成其工作:

  1. 返回指向原始字符串的指针;和

  2. 将找到的每个分隔符替换为NULL。

因此,所有内容都就位,并且不需要分配任何内存。

答案 4 :(得分:0)

这与strtok()有什么关系?如果你分配内存,你需要释放它。您的应用程序决定分配和释放内存取决于您。但是如果你将内存传递给strtok(),那么只要内存被分配或释放,就没有任何区别。