Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
与strtok一起使用的C自由变量_C_Pointers_Undefined Behavior_Strtok_Invalid Pointer - Fatal编程技术网

与strtok一起使用的C自由变量

与strtok一起使用的C自由变量,c,pointers,undefined-behavior,strtok,invalid-pointer,C,Pointers,Undefined Behavior,Strtok,Invalid Pointer,我已经看到过类似的帖子,但我发现有一点不同,让我走错了方向 我有以下代码: char * token_one = strtok(my_buffer, " ,.-"); char * token_two = strtok(NULL, " ,.-"); free(token_one); free(token_two); 我看到一篇文章,人们说strtok使用的变量不应该被释放,但为什么在执行这段代码时我会得到这样的结果: 免费代币(无误) freetoken\u two我得到无效指针 为什么我在

我已经看到过类似的帖子,但我发现有一点不同,让我走错了方向

我有以下代码:

char * token_one = strtok(my_buffer, " ,.-");
char * token_two = strtok(NULL, " ,.-");

free(token_one);
free(token_two);
我看到一篇文章,人们说strtok使用的变量不应该被释放,但为什么在执行这段代码时我会得到这样的结果:

免费代币(无误)

freetoken\u two我得到无效指针

为什么我在freetoken_one中没有错误?处理这个问题的正确方法是什么?

如果你看看strtok是如何工作的,就会立刻明白:

对strtok的第一个调用返回给定的指针,通过用NUL字节替换下一个分隔字符来修改指针指向的字符串。 以NULL作为第一个参数完成的任何后续调用都对保存的指针进行操作,该指针从前面指向替换字符后面的指针。 因此,当您的my_缓冲区来自malloc时,第一个免费调用成功。第二个失败是因为,为什么不应该呢?它不是来自malloc等人,因此对它调用free是未定义的行为。

指针my\u buffer似乎指向动态分配的字符数组

如果数组中存储的字符串不是从其中一个字符开始,.-则从函数strtok返回的指针标记\u one将具有与指针my\u缓冲区相同的值。因此,它可以用来释放分配的内存

指针标记_指向字符串的中间。因此,它的值并不指向以前分配的内存。那么这个电话之后的程序呢

free(token_two);
具有未定义的行为

此声明

free(token_two);
如果从函数strtok的调用返回的指针标记_two是空指针,则该标记将有效。但在这种情况下,调用free不会执行任何操作

考虑两个例子

第一个是

#include <stdio.h>
#include <stdlib.h>

int main(void) 
{
    char *p1  = malloc( 10 );
    char *p2 = p1;

    free( p2 );

    return 0;
}

strtok的返回值指向原始字符串。如果我的_缓冲区是一个已分配的对象,那么这可能不会失败。然而,这是另一个导致未定义行为并期望您总是得到错误的示例,就像在访问任何对象之外的内存时期望segfault一样。正确的处理方法是停止释放返回值的尝试,并阅读strtok上的文档。如果需要释放任何内容,它将是my_缓冲区,但前提是该缓冲区是动态分配的,并且只有在您完成对令牌的访问之后。如果token_one与my_buffer相同,那么free是有效的。通常,您不能释放strtok的结果。例如,您可以将strtok返回的字符串复制到malloc或非标准strdup函数分配的缓冲区中,然后释放该缓冲区。您需要了解strtok会修改原始字符串,而不会分配新字符串。与malloc+free签订的合同没有指定free将检测错误。有时可能是这样,但你不能依赖它。strtok每次都给我指向下一个标记的指针,并在标记的末尾加上一个终止符号?@user4789408它的定义大致是这样的,是的。@user4789408是的,但这段内存不是新的内存块,而是初始字符串的一部分。一旦释放第一个指针,通过第二个指针进行的任何访问都将是非法的,因为它指向的内存区域不再是您的。
#include <stdio.h>
#include <stdlib.h>

int main(void) 
{
    char *p1  = malloc( 10 );
    char *p2 = p1 + 5;

    free( p2 );

    return 0;
}