strtok 的一个可能被忽略的细节

最近帮他们查了一下线上出现了一个神奇的 bug,先加载A库再加载 B 库 和 先加载 B 库再加载 A 库,会有不一致的行为,看起来不一致的行为是环境变量引起的,仔细排查了发现是strtok引起的,运行时会偷偷抹掉原本的字符串,稍微科普一下。

一、问题代码

这段代码本意是把 data  按照冒号拆开,分别访问每一项,打印出来,看起来是没什么问题的,但事实并非如此,输出的结果是

发现 data  是被修改过的,其中冒号的位置都被替换为 \0  了,这个是 strtok_r 偷偷干的一件事。所以,将来有人再把 data 当做string处理时,就只能读到 path1 了。

二、另一个测试样例

同样,使用 strtok  也会这样,会把冒号覆盖为 \0 。

三、一些细节

这时候问题就解决了,库 A 中使用这种方式访问环境变量 PATH,暗中已经将 PATH 改掉了,导致库 B 中访问的 PATH 其实是残缺的环境变量。

Q:为什么环境变量可以被直接写值?

A:在C里, getenv  的声明是 char * getenv(const char *name) ,没有说是const,所以编译是可以通过的;其次,有个 linux 的常识,环境变量默认是存在栈上的,在程序刚运行时的栈上,读写肯定是允许的。

综上,使用 strtok 时一定要保证字符串是临时使用的串,使用完就丢弃掉,因为里面内容不可靠了。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*

code