C 使用strtok\u r时指针无效

C 使用strtok\u r时指针无效,c,dynamic-memory-allocation,free,c-strings,strtok,C,Dynamic Memory Allocation,Free,C Strings,Strtok,运行我的代码(如第一个代码块所示)时,出现以下错误: “./a.out”中出现错误:free():无效指针:0x0000000001e4c016*** 我找到了一个修复程序(如第二个代码块所示),但我不明白为什么会发生错误 我阅读了关于strtok_r的文档,但我不明白为什么将“str”指定给一个新字符*可以解决这个问题 “rest=str”不是意味着rest和str指向同一个内存块吗。这是如何解决问题的 破译代码: #include <stdio.h> #include <

运行我的代码(如第一个代码块所示)时,出现以下错误: “./a.out”中出现错误:free():无效指针:0x0000000001e4c016*** 我找到了一个修复程序(如第二个代码块所示),但我不明白为什么会发生错误

我阅读了关于strtok_r的文档,但我不明白为什么将“str”指定给一个新字符*可以解决这个问题

“rest=str”不是意味着rest和str指向同一个内存块吗。这是如何解决问题的

破译代码:

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

int main() 
{ 
    char* str = (char*) malloc(sizeof(char) * 128);
    char* token;
    
    printf("Enter something: ");  
    fgets(str, 128, stdin);
  
    while ((token = strtok_r(str, " ", &str))) { 
        printf("%s\n", token); 
    }
    
    free(str);
    return (0); 
}
#包括
#包括
#包括
int main()
{ 
char*str=(char*)malloc(sizeof(char)*128);
字符*令牌;
printf(“输入某物:”);
fgets(str,128,stdin);
而((token=strtok_r(str,“,&str)){
printf(“%s\n”,标记);
}
自由基(str);
返回(0);
}
固定代码:

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

int main() 
{ 
    char* str = (char*) malloc(sizeof(char) * 128);
    char* token; 
    char* rest = str; 
    
    printf("Enter something: ");  
    fgets(str, 128, stdin);
  
    while ((token = strtok_r(rest, " ", &rest))) { 
        printf("%s\n", token); 
    }
    
    free(str);
    return (0); 
}
#包括
#包括
#包括
int main()
{ 
char*str=(char*)malloc(sizeof(char)*128);
字符*令牌;
char*rest=str;
printf(“输入某物:”);
fgets(str,128,stdin);
而((token=strtok_r(rest,“,&rest)){
printf(“%s\n”,标记);
}
自由基(str);
返回(0);
}

显然,调用
strtok\u r
会更改指针
str
,该指针作为第三个参数通过引用传递给调用

while ((token = strtok_r(str, " ", &str))) { 
                                   ^^^^
    printf("%s\n", token); 
}
因此,在调用函数后,指针
str
可以指向原始字符串内部。因此,它不会存储调用
malloc
后的值

因此,使用辅助变量rest可以将初始值保留在指针
str

请注意,您没有正确调用该函数。下面是它的描述

在第一次调用
strtok_r()
时,
str
应指向要调用的字符串 解析,并忽略
saveptr
的值。在随后的调用中,
str
应为
NULL
saveptr
自上一个 打电话


因此,对于函数的第二次和后续调用,第一个参数应为
NULL

。显然,调用
strtok\r
会更改指针
str
,该指针作为第三个参数通过引用传递给调用

while ((token = strtok_r(str, " ", &str))) { 
                                   ^^^^
    printf("%s\n", token); 
}
因此,在调用函数后,指针
str
可以指向原始字符串内部。因此,它不会存储调用
malloc
后的值

因此,使用辅助变量rest可以将初始值保留在指针
str

请注意,您没有正确调用该函数。下面是它的描述

在第一次调用
strtok_r()
时,
str
应指向要调用的字符串 解析,并忽略
saveptr
的值。在随后的调用中,
str
应为
NULL
saveptr
自上一个 打电话

因此,对于函数的第二次和后续调用,第一个参数应为
NULL

,您应该编写:

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

int main() 
{ 
    char  str[128];
    char *token; 
    char *rest = str; 
    
    printf("Enter something: ");  
    fgets(str, sizeof str, stdin);
  
    for (token = strtok_r(rest, " ", &rest);
         token = strtok_r(NULL, " ", &rest);
         /* just nothing here */)
    { 
        printf("%s\n", token); 
    }
    
    return (0); 
}
#包括
#包括
#包括
int main()
{ 
char-str[128];
字符*令牌;
char*rest=str;
printf(“输入某物:”);
fgets(str,str的大小,stdin);
for(token=strtok_r(rest),“,&rest);
令牌=strtok_r(NULL,“,&rest);
/*这里什么都没有*/)
{ 
printf(“%s\n”,标记);
}
返回(0);
}
  • 首先,您不需要为
    str
    分配内存,因为您可以定义一个本地数组来存储数据。您可以使用
    sizeof
    操作符,这样,如果您决定更改
    str
    的大小,您就不会冒两处不更新的风险。在使用
    malloc
    的情况下,最好
    #定义一个常量来保存该值,同时在使用分配的缓冲区大小的任何地方使用该常量
  • 其次,never强制转换
    malloc
    的返回值。相信我,这是一个非常坏的习惯。当您执行强制转换时,您会告诉编译器您知道自己在做什么。铸造
    malloc
    的值是C语言中没有
    void
    类型时遗留下来的(直到80年代中期)。很久以前,
    malloc()
    用于返回一个
    char*
    ,它通常不是您想要的指针类型,您必须强制转换指针以匹配您正在使用的指针。不建议在2021年强制转换
    malloc()
    返回值,但强烈建议不要这样做,因为许多错误都来自于强制转换(当你做了一些不好的事情时,编译器会警告你,但如果你抛出这个值,它不会警告你,通常这会被解释为你告诉编译器你是故意做了一些奇怪的事情,因此编译器会闭嘴,不再多说)
  • 第三,如果要提取字符串中的所有令牌,第一次需要调用
    strtok()
    (或他的朋友
    strtok\u w
    )当第一个参数指向字符串的开头时,但是其余的调用必须使用
    NULL
    作为第一个参数,
    否则您将在刚刚返回的字符串中搜索,而不是在第一次出现之后。您的问题不是使用
    strtok
    strtok\r
    ,因为
    strtok\u r
    只是
    strtok
    的可重入版本,它允许您在第一个线程内启动嵌套循环,或者从不同线程调用它
    • 你应该写:

      #include <stdio.h> 
      #include <string.h> 
      #include <stdlib.h>
      
      int main() 
      { 
          char  str[128];
          char *token; 
          char *rest = str; 
          
          printf("Enter something: ");  
          fgets(str, sizeof str, stdin);
        
          for (token = strtok_r(rest, " ", &rest);
               token = strtok_r(NULL, " ", &rest);
               /* just nothing here */)
          { 
              printf("%s\n", token); 
          }
          
          return (0); 
      }
      
      #包括
      #包括
      #包括
      int main()
      { 
      char-str[128];
      字符*令牌;
      char*rest=str;
      printf(“输入某物:”);
      fgets(str,str的大小,stdin);
      对于(令牌=strtok)_