gets puts and fflush
gets puts and fflush
请解释当输入的字符串大于指定的长度时的输出
#include<stdio.h>
int main()
{
char name[21],address[31];
puts("enter a name(max 21 characters)");
gets(name);
fflush(stdin);
puts("enter an address(max 31 characters)");
gets(address);
fflush(stdin);
puts("your name is:");
puts(name);
puts("Your address is:");
puts(address);
return 0;
}
当您输入超过要求的大小时,由于get不检查边界,您将得到未定义的行为,并且过多的字符可以(或不能,未定义的行为)写入保留的字符之后的空间。你应该在C中使用fgets(它有边界检查),在c++中使用std::getline。
大多数C编译器会在堆栈上分配name
和address
,在内存中彼此相邻。我在一台Linux机器上用GCC对它进行了测试,在内存中address
位于name
之后;其他的C编译器也可以反过来做。出于内存对齐的原因,编译器也可能在name
和address
之间分配一些未使用的空间;虽然这对于字符数组来说并不常见。
假设address
在name
之后。内存是这样分配的(最低的地址在上面):
name[0]
name[1]
name[2]
...
name[19]
name[20]
address[0]
address[1]
address[2]
...
address[29]
address[30]
base pointer
return address
stack frame of caller
正如mafso所指出的那样,字符串以后跟NUL字符存储,因此名称最多应该是20个字符(它的最后一个字符将在name[19]
中,NUL结束符在name[20]
中),地址不应超过30个字符。
输入一个21个字符的名称,NUL结束符将在address[0]
中,之后立即被地址覆盖。任何超过21的额外字符也将被覆盖。puts(name)
将打印存储在name
中的21个字符,后面跟着用户在address
中输入的字符;实际上,姓名和地址是连接在一起的。puts(address)
将以正常方式打印地址,因为它在address[0]
处开始打印。
任何尝试输入超过30个字符的地址,将覆盖基指针和/或返回地址,这很可能使函数main
在返回时崩溃。显然,当您输入超过51个字符的名称时,也会发生同样的情况。
通过精心设计将覆盖返回地址的多余字符,有可能使程序发生其他事情而不是崩溃。有技巧的黑客可以利用这带来好运;这就是为什么缓冲区溢出漏洞如此危险。
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- 为什么C++逐位AND运算符在不同大小的操作数中表现为这样
- 为什么 Clang 不允许"and"作为函数名称?
- 位阵列上的快速AND运算
- 是否可以在 C++03 中定义'move-and-swap idiom'等效项
- BoostPython and CMake
- OpenSSL BIO and SSL_read
- Gurobi GRBModel and GRBmodel in C++
- std::visit and std::variant usage
- SHBrowseForFolder with BIF_BROWSEFORCOMPUTER and SHGetPathFr
- Directx12 and keystrokes
- different between int **arr =new int [ n]; and int a[i][j]?
- C++ getenv and setenv
- Inference pytorch C++ with alexnet and cv::imread image
- Visual Studio 2019 C++ and std::filesystem
- 保证逻辑 AND 表达式中的函数调用
- fflush() 没有按预期工作
- python ctypes and C++ pointers
- C++ const char with .begin() and .end()
- gets puts and fflush