繁体   English   中英

strlen()的奇怪行为,在代码中的不同位置使用时会提供不同的输出

[英]Strange behavior of strlen(), giving different output when used at different place in code

码:

#include<iostream>
#include<stdio.h>
int main()
{
        char ch[10];
        std::cout<<"\n\n\n\n\n\n\n";
        std::cout<<"Enter the string: ";
        gets(ch);
        std::cout<<strlen(ch)<<"\n";
        std::cout<<ch<<"\n";
        std::cout<<"sizeof ch"<<sizeof(ch)<<"\n";
        int len=strlen(ch);
        std::cout<<strlen(ch)<<"\n";
        std::cout<<len<<"\n";
        std::cout<<"second last="<<ch[len-1]<<" last="<<(int)ch[len]<<"\n";
        std::cout<<"\n\n\n\n\n\n\n";
        return 0;
}
OUTPUT:

 1. On giving input within defined range(i.e less than 10)

Enter the string: 12345678
8
12345678
sizeof ch10
8
8
second last=8 last=0

 2. On giving input beyond defined range

Enter the string: 12345678901234
14
12345678901234
sizeof ch10
13
14
second last= last=0



Enter the string: 123456789012345678
18
123456789012345678
sizeof ch10
13
18
second last=8 last=0

我知道不应使用gets用法,但我仍然想了解内部发生了什么,为什么输出的最后三行给出13?

唯一真正的答案是不确定的行为。 一旦你访问内存超过数组的结尾,就gets确实,如果输入过大,什么事情都可能发生。

如果我猜的话:最有可能的解释是,放置编译lench内存。 因此,分配给len将会覆盖从数组末尾溢出的一些输入。 该值的某些字节将为零(因为它是一个小数字),因此,在找到这些字节之一时,对strlen的下一次调用将停止,从而提供比以前小的值。

在分配给len之前和之后,也许内存布局看起来像这样。 我假设使用ASCII编码,因此'0'为48, '1'为49,依此类推。我假设int有四个字节,以“ little-endian”顺序排列,内存中的最低有效位在前,并且需要要在四字节边界上对齐,需要两个填充字节才能将其存储在数组之后。

| ch, 10 bytes                  | pad   | len, 4 bytes| other    |
| 49 50 51 52 53 54 55 56 57 48 | 49 50 | 51 52 53 54 | 55 56 00 | before
| 49 50 51 52 53 54 55 56 57 48 | 49 50 | 18 00 00 00 | 55 56 00 | after

您可以看到,在这种情况下第二次调用strlen会在将零值字节解释为字符串的末尾之前找到13个字符。 这符合您的观察。

如您所说,从不使用gets因为无法避免甚至可靠地检测缓冲区溢出。 使用固定大小的数组时要格外小心,并且比C风格的内存处理更喜欢更友好的C ++习惯用法。 使用std::string可以完全避免这种惨败。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM