C语言中strlen的安全使用:如何处理未终止的char数组避免溢出
结论
- 标准库
strlen完全无法安全处理不带'\0'终止符的char数组,没有任何不额外传参就能安全调用它的方法。因为strlen的实现逻辑就是从传入的指针起始位置向后遍历直到遇到'\0'为止,若输入没有终止符,必然会越界访问数组外的内存,引发未定义行为。 - 唯一通用的修复方案就是你提到的,修改函数签名新增长度上限参数,结合安全的长度计算函数使用。
具体实现方案
方案1:使用标准库strnlen
strnlen是POSIX.1-2008、C11标准正式纳入的字符串处理函数,专门针对不知道输入是否带终止符的场景,函数原型为:
size_t strnlen(const char *s, size_t maxlen);
它最多只会扫描前maxlen个字节:如果在范围内找到'\0'就返回实际字符串长度,找不到就直接返回maxlen,不会越界访问内存。
修改后的代码如下:
void foo(char *c, size_t MAXSIZE) { size_t a = strnlen(c, MAXSIZE); // 后续处理:如果a等于MAXSIZE,说明输入不是合法C字符串,需要单独处理,不能直接传入strcpy、printf("%s")等要求合法字符串的函数 }
方案2:兼容旧环境自行实现安全求长逻辑
如果你的开发环境不支持strnlen,可以自己实现等价逻辑,代码参考:
size_t safe_strlen(const char *s, size_t maxlen) { if (s == NULL || maxlen == 0) return 0; size_t len = 0; while (len < maxlen && s[len] != '\0') { len++; } return len; }
补充说明
C语言的裸字符指针本身不携带任何关联数组的长度信息,没有任何通用方法可以在仅拿到指针的前提下,判断指针指向内存的有效范围,也无法确定后续内存中出现的'\0'是不是属于当前数组的终止符。因此必须由调用方传入数组的长度上限,没有其他绕路的办法。
内容的提问来源于stack exchange,提问作者Klinda
相关产品推荐
相关产品推荐

