和我一样,想必许多人都有过用下列代码检查字符串长度,认为这样可以防止字符串长度非法引发的错误。
len = strlen(name);
if(len > xxx) return error;
但这几天调试文件系统,看着处理文件名的程序中的strlen函数,总觉得特别刺眼。要是用户错误,name传进来一个无限长(32位机上,当然不会超过4G)的字符串怎么办,不要忘了,name是指针,C语言中,指针什么事都能干得出来的!
于是查ansi c的标准文本,文本第7章中有标准库的定义,定义中并没有对strlen允许接受的字符串长度做任何限定。
于是实际测试了以下,CPU是44b0x,64M,cache全开,gcc编译器,做了一个4M长的字符串,测试伪代码如下:
初始化4M字符串;
启动定时器;
调用strlen;
读取定时器。
执行结果是strlen正确地报告了串长度,用时315毫秒,平均每个字符75nS。
结果吓了我一跳,心想,如果串长度接近4G,那执行时间岂不是要300多秒,要是用不带cache的CPU,岂不要超过10分钟?速度再慢一些的呢?而且,问题不在于具体要多长时间,而是strlen的执行时间的不确定性。我们知道,嵌入式系统经常用于实时环境,执行时间不确定是很危险的。本来是想买个保险,谁知买来一个炸弹!
于是决定不使用strlen,而是自己编写一个rtstrlen函数代替,该函数的原型是
sint32_t rtstrlen(const char *s,uint32_t over);
over用于限定输入字符串的最大长度,如果超过over则返回-1,over=0则不限定,与strlen函数功能相同。