问题
If I use std::cin, std::cout and std::string, is there any possibility that someone will exploit the buffer overflow?
I ask this because I still see a lot of people that still use null-terminated strings instead of standard containers in C++.
回答1:
It depends. Of course, when you use C-style code/API's, there is no difference.
But using STL or C++ idioms doesn't guarantee that you're safe.
C++ gives you the choice, always. Contrast these two near-identical twins:
int n;
std::cin >> n;
std::string s(n, '*'); // create a data store of given size
std::vector<char> v(1000);
std::copy(s.begin(), s.end(), v.begin()); // NOT safe if n > 1000
safe variant:
int n;
std::cin >> n;
if (n > MAX_LIMIT)
throw std::runtime_error("input too large");
std::string s(std::min(0, n), '*'); // note input sanitation
std::vector<char> v;
v.reserve(1000);
std::copy(s.begin(), s.end(), std::back_inserter(v)); // safe
回答2:
One of the big reasons you still see people using C-strings in C++ (besides not knowing about strings, or being stuck in a C mindset), is that std::istream::getline
works with char pointers and not strings. As do a huge number of other parts of the library. Part of the reason for that was so that "you don't pay for what you don't use". IE: people that just want to get a line of text shouldn't have to instantiate a string
(thereby also having to pull in another template class) to do so. You can use std::getline
to get lines as strings if you want them, but that's not obvious. So some people think they still need to use char buffers to get a line of text.
(Seems a lot of that is changed in C++11, and you can use string
s in a lot of places where you had to pass a char*
before. Maybe that'll help a bit with the C-in-C++ problem.)
Standard strings and streams are designed to be overflow-resistant, and are all-around safer than a char pointer (at least when they're not used like a plain old array/pointer; blindly using str
's iterator without regard for str.end()
is usually a bad idea, but str.push_back()
, str += "text"
, str.at(x)
, and stream insertion/extraction operators are perfectly safe). If you can use them, i highly recommend you do so.
回答3:
Still lot of people use null-terminated strings because they do not realize the convenience of using std::string
and they are really writing procedural c++ not c++.
Most programmers migrating/migrated from c to c++ are the ones who still use null-terminated strings.
It is perfectly safe and you should use std::string
in c++ wherever you can.
std:string
actually protects you against buffer overflow(unlike c strings) by dynamically growing in size as the data added to it is increased.
An code sample:
#include <iostream>
using namespace std;
int main()
{
string str("std::String");
for (int i=0; i<20; ++i)
{
cout << "capacity is " << str.capacity() << endl;
str += " ,is Overrun safe string";
}
return 0;
}
Output:
capacity is 11
capacity is 35
capacity is 70
capacity is 140
capacity is 140
capacity is 140
capacity is 280
capacity is 280
capacity is 280
capacity is 280
capacity is 280
capacity is 280
capacity is 560
capacity is 560
capacity is 560
capacity is 560
capacity is 560
capacity is 560
capacity is 560
capacity is 560
回答4:
C-strings may be faster, because std containers have to support some functionality that they support. So, nobody can point the best choice for all times.
来源:https://stackoverflow.com/questions/8015355/are-c-strings-and-streams-buffer-overflow-safe