使用strlen()有什么缺点?
如果有时在TCP通信中,NULL字符出现在字符串中,而不是我们发现字符串的长度只能为空字符。
我们无法找到字符串的实际长度。
如果我们使用此strlen函数的其他替代方法,那么它也会在NULL字符处停止。那么我可以用哪种方法找出C中的字符串长度
答案 0 :(得分:2)
要从“TCP通信”中读取,您可能正在使用read
。 read
的原型是
ssize_t read(int fildes, void *buf, size_t nbyte);
,返回值是读取的字节数(即使它们是0
)
所以,假设你要读取10个字节,所有这些都是0.你有一个数组足以容纳所有数据
int fildes;
char data[1000];
// fildes = TCPConnection
nbytes = read(fildes, data, 1000);
现在,通过检查nbytes
,你知道你已经读了10个字节。如果您检查data[0]
到data[9]
,则会发现他们有0
;
答案 1 :(得分:1)
如果运行时库提供strcpy()
和strcat()
,那么它肯定会提供strlen()
。
我怀疑你将来自ASCII代码NULL的无效指针值NUL混淆为零字符值,表示字符串结束到许多C运行时函数。
因此,无需在字符串中插入NUL值,也无需检测它。
对更新问题的回应:
由于您似乎正在处理二进制数据,因此字符串函数不适合 - 除非您可以保证流中没有NUL。但是,出于这个原因,大多数TCP / IP消息都使用包含随后字节数的字段的标头。
答案 2 :(得分:1)
是的,strlen()
使用终止字符\0
也称为NUL。大多数str *函数都是这样做的。可能存在来自文件/命令行/套接字的数据不包含此字符的风险(通常,它们不会:它们将被\n
- 终止),但它们的大小也将由您使用的read()
/ recv()
函数。如果这是一个问题,你总是可以使用比那些函数声明的缓冲区稍大的缓冲区,例如
char mybuf[256+4];
mybuf[256]=0;
int reallen=fgets(mybuf, 256, stdin);
// we've got a 0-terminated string in mybuf.
如果您的数据可能不包含\0
,请将strlen(mybuf)
与reallen
进行比较,如果不同,则使用错误代码终止会话。
如果您的数据可能包含0
,那么它应该作为缓冲区而不是字符串处理。必须将大小放在一边,并且应使用memcpy
/ memcmp
函数而不是strcpy和strcmp。
此外,您的网络协议应该非常清楚地表明通信的不同部分是否需要字符串或二进制数据。例如,HTTP提供了许多方法来告知传输的有效载荷的实际大小。
这不是特定于“嵌入式”程序,但它已成为每个程序中的主要问题,以确保不会发生远程代码/脚本注入。如果通过“嵌入式”,你的意思是你处于一个非抢先的环境中并且只有有限的时间可用于执行某些操作...那么是的,你不想最终扫描2GB的输入比特(从不 - 出现)\0
。上述技巧或strnlen(在另一个答案中提到)可以用来确保不是这种情况。
答案 3 :(得分:1)
“嵌入式”让我觉得这是一个红鲱鱼。
如果您正在处理嵌入式NUL可能有效的二进制数据,那么您无法期望strlen
获得有意义的结果。
如果您正在处理字符串(因为该术语是在C中定义的 - 由NUL终止的非NUL数据块),那么您可以正常使用strlen
。
“嵌入式”系统只会影响到这一点,因为处理字符串可能不常见,而处理二进制数据则更常见。
答案 4 :(得分:1)
使用strnlen而不是strlen来避免strlen的问题更安全。 strlen问题无处不在,而不仅仅是嵌入式问题。许多字符串函数都很危险,因为它们会永远或者直到零点被击中,或者像scanf或strtok一样直到模式被击中。
记住tcp是一个流而不是一个数据包,你可能需要等待多个或多个数据包并将数据拼凑在一起,然后才能尝试将其称为字符串。假设有效载荷无论如何都是asciiz字符串,如果原始数据不使用字符串函数则使用其他解决方案。