当字符数组被cin填充时,它是如何超大的?得到(大小)

How is char array an oversize when filled by cin.get(a, size)

本文关键字:何超大 得到 大小 数组 字符 cin 填充      更新时间:2023-10-16
char a[3];
cin.get(a, 10);
cout << a << endl;
  • 输入:xxxxxxxxxxxxxxxx
  • 输出:期望:xx;收到:xxxxxxx <-长度10

问题是它是如何工作的固定大小的数组,但在它的"超过长度的内容"。

输出行为不是未定义的,但是在我的机器上长度恰好是10。

命令功能cin.get接收一个存储数据的指针。如果该char数组所指向的内存不足以容纳所读取的数据,则函数执行的行为是未定义的。

可能输出xx、yy或xxxxxxx。你不应该问为什么,如何等,因为它是未定义的。

当调用cin.get(c_type_str, len)时,调用者有责任确保c_type_str至少可写入len字节。

缓冲区溢出(或bufferoflow)是一个未定义的行为。除了相信调用者传递的长度是正确的之外,没有简单的方法来识别c string(应该由空字符追加的字符数组)中的bufferflow。因此,该函数默默地完成了它(+你很幸运没有发生任何不好的事情),而不是抛出一些异常或类似的东西。

一个未定义的行为就是未定义的行为,理解你的输出的最好方法就是停止做它。(缓冲区溢出)

使用std::string而不是char array来读取输入可以在这里帮助您。std::string是灵活的长度,如果存在读取超大输入而不是做未定义的事情的威胁,将抛出std::bad_alloc异常。

编辑
关于编辑部分的下一个问题

的问题是它是如何工作的固定大小的数组,但cout"超长内容"

char arrays在c++中是特殊的,以保持与c strings的反向兼容。当您使用std::cout打印c string(以空字符结束的字符数组)时,只要不遇到NUL字符(),它就会继续打印字符。由于同样的原因,std::cout将不尊重数组的实际大小。

您看到的额外字符将位于数组结束后的连续内存部分。它可能尚未被认领,或者可能正在被其他用户定义的变量,一些内建变量,其他线程等使用。

也许我错了,但是当你创建一个变量,你持有该变量的内存空间。如果你填了更多的内存,那么你就占用了为其他变量或者其他程序保留的内存空间,这是很危险的。Char数组必须有一个结束字符(NULL),告诉编译器这是变量的结束,如果你用其他填充NULL字符,那么编译器将继续读取其他变量的空间。

例如:

内存中有两个变量。VAR A和VAR A旁边的VAR b

VAR ,,,, VAR b
, AAA0 ,,, BBB0

程序读取VAR A并得到AAAA,但是如果你用AAAA填充VAR A,那么:
VAR ,,,, VAR b
, AAAA ,,, BBB0

则程序读取VAR A并得到AAAABBB0

如果用AAAAAA填充VAR A,则为:
VAR ,,,, VAR b
, AAAA ,,, AAB0

您正在覆盖其他变量,程序读取AAAAAAB0

这就是我对变量的理解。也许我错了,有人知道得更清楚。