首先,说明一下,我不是一个C程序猿,也不是一个C++程序猿,我从入门开始真正学习的编程语言以及正经用过的变成语言,也就是Java和C#,虽然我对其他的语言都非常感兴趣,同时也写过一些Python的脚本和C的代码(主要集中在JNI)。
由于这些年来的编程习惯,我认为字符串都应该会有自动获取其长度的方法,在前几天的工作中就碰到需要使用这个方法的场景了。由于我对strlen()使用的不慎,导致程序输出时而正确时而错误,最终定位到是因为使用strlen()方法获取字符串长度在多次执行后的输出不等,导致程序出现了不可控的情况。
那么是否是因为strlen()方法的问题呢,我自己首先十分肯定绝对不会是这个方法的问题,这些方法在时间和实践中都尼玛得到过太多的验证,且看Linux中的实现:
[c light=”true”]
#ifndef __HAVE_ARCH_STRLEN
/**
* strlen – Find the length of a string
* @s: The string to be sized
*/
size_t strlen(const char * s)
{
const char *sc;
for (sc = s; *sc != '\0'; ++sc)
/* nothing */;
return sc – s;
}
#endif
[/c]
这么简洁的实现,多么漂亮啊。肿么可能会出错捏?好吧,实际的应用场景是我需要将一个从C#运行时托管层将一个byte数组传入Native层,在Native层面做一些操作的时候呢,我直接使用了strlen()函数来确认当前byte数组的长度,尼玛脑残啊。托管层byte数组虽说可以认为是Native层的unsigned char数组,但是我并木有意识到C层的字符串都是需要’\0’来作为终止符滴,显然从托管层传入的数组中不会自行添加这个到数组中。所以才会出现偶尔内存中该数组后面确实没有任何值,那么strlen()函数在刚好读取到数组后的值为空时,那么其长度刚好正确,在某些时候该数组后连续的内存地址中并不为空,那么strlen()就会返回一个错误的长度,而我的逻辑代码又依赖于该长度,所以你只到的,Just Fucked Up!
所以在托管层申请的内存,传入Native层面时,一定要注意两个平台下对某些概念处理的不一致,否则到时候又得吃自己的狗屎了。WTF。