14

当您在 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 之前被分配。我应该在使用 strtok 后释放原始字符串还是为我们完成这项工作?另外,如果'line'没有被分配并且我尝试使用上面的函数会发生什么?改为执行以下操作更安全吗?(假设程序员如果知道该行没有被分配就不会调用 free)

调用

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
}
4

5 回答 5

9

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

改为执行以下操作更安全吗?

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

进一步阅读: strtok()

于 2011-02-15T05:58:34.773 回答
5

值得解释的是strtok,它的工作原理是:

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

  2. 用 NULL 替换它找到的每个分隔符。

因此,一切都在原地,并且不需要分配任何内存。

于 2019-04-11T21:41:42.123 回答
4

在您问题的评论中,您说您“多次在'line'上调用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' 应该由分配它的相同上下文释放(或不释放),因此对 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 的工作方式解释起来有点复杂,但你已经掌握了重要的部分——它不分配或释放任何内存。相反,它通过修改您传递给它的字符串来工作。

于 2011-02-15T07:17:55.343 回答
0

这有什么关系strtok()?如果分配内存,则需要释放它。您的应用程序决定分配和释放内存的位置取决于您。但是,如果您将内存传递给strtok(),那么就分配或释放内存的情况或时间而言,这没有任何区别。

于 2011-02-15T05:47:40.613 回答
0

strtok 不会比 strlen 更多地释放内存。你为什么会期望它?它会释放什么内存?也许你认为 strtok 需要释放内存是因为它存储了一个 NUL,但内存的内容是无关紧要的。当你分配内存时,分配器会跟踪你分配的块的大小,当你释放它时,整个块就会被释放。

于 2011-02-15T09:09:33.340 回答