如果存储字符串的char数组小于字符串,则C ++真正在哪里存储字符串? [英] Where C++ really stores a string if the char array that stores it is smaller than a string is?

查看:70
本文介绍了如果存储字符串的char数组小于字符串,则C ++真正在哪里存储字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在测试《 C ++ Premiere》一书中有关C ++字符串的示例.

I'm testing an example about strings in C++ from "C++ Premiere" book.

const int size = 9;
char name1[size];
char name2[size] = "C++owboy";   // 8 characters here

cout << "Howdy! I'm " << name2 << "! What's your name?" << endl;

cin >> name1;  // I input "Qwertyuiop" - 11 chars. It is more than the size of name1 array;

// now I do cout
cout << "Well, your name has " << strlen(name1) << " letters";  // "Your name has 11 letters".
cout << " and is stored in an array of " << size(name1) << " bytes"; // ...stored in an array of 9 bytes.

将11个字符存储在仅8个字符+'\ 0'字符的数组中怎么可能?它在编译时会变得更宽吗?还是字符串存储在其他地方?

How it can be that 11 chars are stored in an array just for 8 chars + '\0' char? Is it becomes wider on compilation? Or the string is stored somewhere else?

我也做不到:

const int size = 9;
char name2[size] = "C++owboy_12345";   // assign 14 characters to 9 chars array

但是可以做我上面写的事情:

But can do what I've written above:

cin >> name1;   // any length string into an array of smaller size

这里的窍门是什么?我使用NetBeans和Cygwin g ++编译器.

What is the trick here? I use NetBeans and Cygwin g++ compiler.

推荐答案

这是典型的缓冲区溢出.这就是为什么要把输入放在缓冲区中时总是要检查输入的大小的原因.这是正在发生的事情:

This is a typical buffer overflow. This is why you're always supposed to check the size of input if you're putting it in a buffer. Here is what's happening:

在C ++(和C)中,数组名称只是指向数组第一个元素的指针.编译器知道数组的大小,并将进行一些编译时检查.但是,在运行时,它只会将其视为char *.

In C++ (and C), array names are just pointers to the first element of the array. The compiler knows the size of the array and will do some compile-time checks. But, during runtime, it'll just treat it as a char*.

当您完成 cin>>name1 ,您将一个char *传递给 cin . cin 不知道分配的空间有多大,它所拥有的只是一个指向某些内存的指针.因此,假设您分配了足够的空间,编写了所有内容,并且超过了数组的末尾.这是一张图片:

When you did cin >> name1, you passed a char* to cin. cin doesn't know how big the allocated space is -- all it has is a pointer to some memory. So, it assumes you allocated enough space, writes everything, and goes past the end of the array. Here's a picture:

Bytes   1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
Before  |-----name1 array-------|  |--- other data-|
After   Q  w  e  r  t  y  u  i  o  p  \0 |-er data-|

如您所见,您已经覆盖了数组之后存储的其他数据.有时,这些其他数据只是垃圾,而在其他时候,它很重要,并且可能意味着棘手的错误.更不用说,这是一个安全漏洞,因为攻击者可以使用用户输入来覆盖程序内存.

As you can see, you have overwritten other data that was stored after the array. Sometimes this other data is just junk, but other times it's important and could mean a tricky bug. Not to mention, this is a security vulnerability, because an attacker can overwrite program memory with user input.

关于大小的困惑是因为 strlen 将对字节进行计数,直到找到'\ 0'(空终止符)为止,这意味着它将找到10个字符.另一方面, size(name1)使用由编译器提供的数组的实际大小.

The confusion about sizes is because strlen will count bytes until it finds a '\0' (null terminator), meaning it finds 10 characters. On the other hand size(name1) uses the actual size of the array, provided by the compiler.

由于这些问题,每当您看到将数组作为参数的C函数时,它也会占用数组大小​​.否则,无法分辨出它有多大.为了避免这些问题,最好使用诸如std :: string之类的C ++对象.

Because of these problems, whenever you see a C function that takes an array as an argument, it also takes the array size. Otherwise there's no way of telling how big it is. To avoid these problems, it's much better to use C++ objects like std::string.

这篇关于如果存储字符串的char数组小于字符串,则C ++真正在哪里存储字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆