不同编译器的 strtok() 行为不同
strtok() behavior is different across compilers
我写了一个程序,根据这种格式解析字符串:
somethingsomething:number:
在我的电脑上,这个程序运行完美。
但是,一旦我上传了代码并在学校的计算机上编译了它,strtok()
就会有不同的行为。
例如,对于此字符串:p2test/f4.txt:1:
,在我的计算机上,第一个标记将是 p2test/f4.txt
。但是,在学校的计算机上,令牌最终为 p2test/f4.t
。
代码段如下:
char *token;
char delim[1] = ":";
if ((token = strtok(tmp_string, delim)) != NULL) {
...
}
在这里,tmp_string
将是 p2test/f4.txt:1:
。
这里是我电脑的编译器版本:gcc version 4.9.1 (Ubuntu 4.9.1-16ubuntu6)
这里是我学校的编译器版本:gcc version 4.8.1 20130909 [gcc-4_8-branch revision 202388] (SUSE Linux)
除了评论中指出的几个问题外,代码似乎还有一个更大的问题。根据man pages中getline()函数的描述:
If *lineptr is set to NULL and *n is set 0 before the call, then get‐
line() will allocate a buffer for storing the line. This buffer should
be freed by the user program even if getline() failed.
Alternatively, before calling getline(), *lineptr can contain a pointer
to a malloc(3)-allocated buffer *n bytes in size. If the buffer is not
large enough to hold the line, getline() resizes it with realloc(3),
updating *lineptr and *n as necessary.
您没有初始化 tmp_string,因此它的值是指向某个随机地址的一些未初始化的垃圾,并且发生了上述 getline() 的第二种替代行为。
我觉得这像是未定义的行为。
P.S。您确实将长度值初始化为 0 字节,根据 getline() 的手册页,这会导致它调用 realloc。因此,在我看来,您的代码最终间接地将垃圾指针传递给 realloc。
另一个问题是你在这里有一个内存覆盖:
char delim[1] = ":";
字符串中有两个字符,不是1个。这样做更安全:
char delim[] = ":";
我写了一个程序,根据这种格式解析字符串:
somethingsomething:number:
在我的电脑上,这个程序运行完美。
但是,一旦我上传了代码并在学校的计算机上编译了它,strtok()
就会有不同的行为。
例如,对于此字符串:p2test/f4.txt:1:
,在我的计算机上,第一个标记将是 p2test/f4.txt
。但是,在学校的计算机上,令牌最终为 p2test/f4.t
。
代码段如下:
char *token;
char delim[1] = ":";
if ((token = strtok(tmp_string, delim)) != NULL) {
...
}
在这里,tmp_string
将是 p2test/f4.txt:1:
。
这里是我电脑的编译器版本:gcc version 4.9.1 (Ubuntu 4.9.1-16ubuntu6)
这里是我学校的编译器版本:gcc version 4.8.1 20130909 [gcc-4_8-branch revision 202388] (SUSE Linux)
除了评论中指出的几个问题外,代码似乎还有一个更大的问题。根据man pages中getline()函数的描述:
If *lineptr is set to NULL and *n is set 0 before the call, then get‐ line() will allocate a buffer for storing the line. This buffer should be freed by the user program even if getline() failed. Alternatively, before calling getline(), *lineptr can contain a pointer to a malloc(3)-allocated buffer *n bytes in size. If the buffer is not large enough to hold the line, getline() resizes it with realloc(3), updating *lineptr and *n as necessary.
您没有初始化 tmp_string,因此它的值是指向某个随机地址的一些未初始化的垃圾,并且发生了上述 getline() 的第二种替代行为。
我觉得这像是未定义的行为。
P.S。您确实将长度值初始化为 0 字节,根据 getline() 的手册页,这会导致它调用 realloc。因此,在我看来,您的代码最终间接地将垃圾指针传递给 realloc。
另一个问题是你在这里有一个内存覆盖:
char delim[1] = ":";
字符串中有两个字符,不是1个。这样做更安全:
char delim[] = ":";