[英]invalid pointer when using strtok_r
When running my code (shown in the first code block), I get this error: *** Error in `./a.out': free(): invalid pointer: 0x0000000001e4c016 ***
I found a fix (which is shown in the second code block), but I don't understand why the error is happening in the first place.运行我的代码时(显示在第一个代码块中),我收到此错误:
*** Error in `./a.out': free(): invalid pointer: 0x0000000001e4c016 ***
我找到了一个修复程序(如图所示在第二个代码块中),但我不明白为什么首先会发生错误。
I read the documentation regarding strtok_r, but I don't understand why assigning "str" to a new char* fixes the problem.我阅读了有关 strtok_r 的文档,但我不明白为什么将“str”分配给新的 char* 可以解决问题。
Doesn't "rest = str" mean that rest and str point to the same block of memory. “rest = str”是否意味着 rest 和 str 指向 memory 的同一块。 How does this fix the problem???
这如何解决问题???
Broken code:损坏的代码:
#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);
}
Fixed code:固定代码:
#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);
}
It looks evidently that a call of strtok_r
changes the pointer str
that is passed to the call by reference as the third parameter.显然,对
strtok_r
的调用更改了指针str
,该指针作为第三个参数通过引用传递给调用。
while ((token = strtok_r(str, " ", &str))) {
^^^^
printf("%s\n", token);
}
So after a call of the function the pointer str
can point inside the original string.因此,在调用 function 之后,指针
str
可以指向原始字符串内部。 So it will not store the value that it had after a call of malloc
.所以它不会存储它在调用
malloc
之后的值。
Thus using the auxiliary variable rest allows to keep the initial value in the pointer str
.因此,使用辅助变量 rest 允许将初始值保留在指针
str
中。
Pay attention to that you are calling the function incorrectly.请注意,您错误地调用了 function。 Here is its description
这是它的描述
On the first call to
strtok_r()
,str
should point to the string to be parsed, and the value ofsaveptr
is ignored.在第一次调用
strtok_r()
时,str
应该指向要解析的字符串,并且忽略saveptr
的值。 In subsequent calls,str
should beNULL
, andsaveptr
should be unchanged since the previous call.在随后的调用中,
str
应该是NULL
,并且saveptr
应该自上次调用以来保持不变。
So for the second and subsequent calls of the function the first argument shall be NULL
.因此,对于 function 的第二次和后续调用,第一个参数应为
NULL
。
You should write:你应该写:
#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);
}
str
, as you can define a local array to store the data.str
分配 memory ,因为您可以定义一个本地数组来存储数据。 You can use the sizeof
operator so you don't run the risk of not updating it in two places if you decide to change the size of str
.sizeof
运算符,这样如果您决定更改str
的大小,就不会冒在两个地方不更新它的风险。 In the case of using malloc
you had better #define
a constant to hold the value while you use the constant everywhere you are using the size of the allocated buffer.malloc
的情况下,您最好#define
一个常量来保存该值,同时在使用分配缓冲区大小的任何地方使用该常量。malloc
.malloc
的返回值。 Believe me, it is a very bad habit.malloc
is a legacy from when there was no void
type in C (this is so far as the middle eighties).malloc
中没有void
类型时的遗留物(直到八十年代中期)。 Once upon a time, malloc()
used to return a char *
which normally was not the type of pointer you wanted, and you had to cast the pointer to match the one your were using.malloc()
用于返回一个char *
,这通常不是您想要的指针类型,您必须强制转换指针以匹配您正在使用的指针。 Casting malloc()
return value in 2021 is not only not recommended, but it is strongly discouraged, as many errors come from having cast it (the compiler warns you when you are doing something bad, but it will not, if you cast the value, normally that is interpreted as you telling the compiler you are doing something weird on purpose, so the compiler shuts up, and doesn't say more)malloc()
返回值,而且强烈建议不要这样做,因为许多错误来自于强制转换(编译器会在您做错事时警告您,但如果您强制转换该值,则不会,通常这被解释为你告诉编译器你故意在做一些奇怪的事情,所以编译器关闭,不再多说)strtok()
(or his friend strtok_w
) with a first parameter pointing to the start of the string, but the rest of the calls have to be done with NULL
as it first parameter, or you'll be searching inside the string just returned , and not behind the first occurrence.strtok()
(或他的朋友strtok_w
)时,第一个参数指向字符串的开头,但调用的 rest 有以NULL
作为第一个参数来完成,否则您将在刚刚返回的字符串中进行搜索,而不是在第一次出现的后面。 Your problem was not about using strtok
or strtok_r
, as strtok_r
is just a reentrant version of strtok
that allows you to start a nested loop, inside the first, or to call it from different threads.strtok
或strtok_r
,因为strtok_r
只是strtok
的可重入版本,它允许您在第一个循环内启动嵌套循环,或从不同的线程调用它。Heap memory management keeps track of base memory addresses for implementing library calls.堆 memory 管理跟踪基本 memory 地址以实现库调用。 We need to preserve those base-addresses to free/reallocate whenever necessary.
我们需要保留这些基地址,以便在必要时释放/重新分配。
Now that you found a way to use strtok_r()
, I prefer the below version:既然您找到了使用
strtok_r()
的方法,我更喜欢以下版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main () {
char orgStr [] = "strtok does not allow you to have 2 pointers going at once on the same string";
for (char *token, *rmdStr = orgStr; token = strtok_r (NULL, " ", &rmdStr); /* empty */) {
printf ("%s\n", token);
}
/* Original string is chopped up with NULCHAR, now unreliable */
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.