Why does the cin extraction operator cause a segfault? - c++

#include <iostream>
using namespace std;
int main() {
char * c;
cin >> c;
return 0;
}
I'm trying to get a C string line from the user whose length is not known. I know that if I declared c as char c[80] instead of char * c then it wouldn't cause a segfault.
However what if I didn't want to restrict the user to 80 - 1 characters? I could use a really big number but that would just waste space.
I would also really like to know why the above program causes a segfault. From what I understand the cin extraction operator (>>) knows to NULL terminate a C string. What exactly is causing the problem?

The program segfaults because the pointer c is not initialized. You need to allocate memory for the buffer before reading the data into it:
char * c = new char[80];
cin >> c;
cout << c << endl;
delete[] c; // Now you need to delete the memory that you have allocated.
To avoid restricting your input to N characters, use strings. They resize dynamically as you need:
string c;
cin >> c;
cout << c;
// You do not need to manage string's memory - it is done automatically

You've allocated no space at all for the string when you use only char *c;. The variable declaration creates a pointer to char which is uninitialized. Then you use cin to read a string into that space. c could point to anything, and in any case will point to memory that doesn't belong to you.
You'll need to allocate space for the string before you try to fill it from cin.
If you don't want to assume a limit on the string length, you can loop and realloc more space until the input is completely read, but as has been mentioned, if you use std::string instead of C strings, then this will be handled for you.

That is because you did not allocate memory for your string.

Related

Declaration of a String of Dynamic Length Using Pointer

I wanted to declare an array with a pointer in character type, and the length of the array can be determined by my input string.
I wrote it in this way:
char *s;
cout << "Enter a string: " << endl;
cin >> s;
I expected that I can initialize the string by the cin operation, but an error showed up when compiling. The error is about "invalid operands to binary expression".
I'm not sure why the lines I wrote was wrong.
I though not only the built in string class is used for declaring an array.
Isn't the string data type in C++ the same as "a character array"?
Isn't the line char *s means the pointer s points to an character array (or string)?
Thank you!
You should use std::string.
It is a class that represents a string of characters. It is different than an old c style array of characters (although internally might contain one).
In your case:
#include <string>
#include <iostream>
std::string s;
std::cout << "Enter a string: " << endl;
std::cin >> s;
Using std::string means memory is managed automatically for you. Specifically with cin it will also be resized to fit the input.
A side note: better to avoid using namespace std - see here Why is "using namespace std;" considered bad practice?.
"the cin operation".
cin is really the source. The real work is done by the overloaded operator>>. And the operator>> which reads to a char* expects that the char* is already allocated to the right size. That's of course a problem with cin, where the size is unknown.
The operator>> overload that reads to std::string will resize the std::string to the right size.
The answer to your question is no, as when you create a type pointer you always have to specify in advance how much memory to allocate. We can imagine that this is what happens with strings, that is to go to fetch the data and arrange the occupied cells in memory at a later time.
Now the real problem is, it is true that you have declared a pointer to a character, but you have not specified how much to allocate for it. It is as if you are saying you want to create a box but you are not specifying the size. I show you the correct method:
char *s = new char[10];
Obviously when using pointers, always remember to deallocate them at the end of use so as not to have any memory leaks.
Taking a summary of the situation, you tried to save a data in a box that you intend to create but does not exist. That is, you have named the box called s which will contain a pointer to a character but you have not yet built/created it in its final size.

cin >> writing out of range?

I have a code
char s[5];
cin >> s;
cout << strlen(s);
cout << endl;
cout << s;
It works even if I input more than 5 chars, for example "qwertyui". Does it mean that I am using not allocated memory?
strlen(s)
is something, but has nothing to do with 5. strlen applies to C strings, which are char arrays, but their length is defined as the numbers of characters until the first zero byte happens.
Now, cin in your second line cannot know how long your char[] is, so it just accepts as much input as there is. You must never use char buffers for input you don't know is well-formed. What you're seeing is a buffer overflow in action. Writing over memory that doesn't belong to any variable you allocated results in undefined behaviour, so your program might just work, crash with e.g. a segfault (accessing memory that the OS never gave you), or overwriting existing part's of your processes' memory, or ā€¦ just do anything, because it's really undefined.
So, you're writing C++, not C. just
string s;
cin >> s;
cout << s.length()
<< endl
<< s;
to avoid dealing with the (very dangerous) C strings.
You're right, it might still echo correctly if you write more than 5 characters. You're simply writing off the end of the buffer, and just blasting the memory that's next to the memory allocated for char s[5]. This is bad for many reasons, including security vulnerabilities. See here for details.
If you can't use string (for whatever reason), use fgets. See here for the documentation on fgets and how it is used. NEVER USE gets. It's almost equivalent to what you've done above, see here for why gets is so dangerous.

Why does this C++ char array seem to be able to hold more than its size?

#include <iostream>
using namespace std;
typedef struct
{
char streetName[5];
} RECORD;
int main()
{
RECORD r;
cin >> r.streetName;
cout << r.streetName << endl;
}
When I run this program, if I enter in more than 5 characters, the output will show the whole string I entered. It does not truncate at 5 characters. Why is that?
How can I get this to work correctly?
You are overflowing the buffer. Put another char array after streetName and you will likely find that it gets the rest of the characters. Right now you are just corrupting some memory on your stack.
In order to limit the input to the size of the receiving array you need to use the length-limiting facilities provided by your input method. In your case you are using cin, which means that you can specify the limit by using its width method
cin.width(5);
cin >> r.streetName;
Because cin sees streetName as a char * and writes to memory and there is nothing to stop writing to *(streetName + 6) and further. This is a form of buffer overrun
The best code in this case is define streetName as a std::string
i.e.
typedef struct
{
std::string streetName;
} RECORD;
Because you're overruning the end of your buffer and in this particular case you're getting away with it. C and C++ make it very easy to "shoot yourself in the foot", but that doesn't mean that you should.
It's a buffer overrun.
C++ does not perform bounds checking on array accesses, and memory does not simply stop at the end of the array. You are writing data to memory that is not part of the array, the consequences of which are non-deterministic, and may sometimes even appear to work.
It is quite likely that if you placed that code into a function, the program would crash when you tried to return from the function, because one likely possibility is that you will have dumped on the function return address on the stack. You may also have corrupted data belonging to the calling function.
The way to do this correctly in c++ is to use a std::string.
#include<iostream>
#include<string>
....
std::string r;
getline(cin, r);
std::cout << r <<std::endl;
For truncated input(with suitably defined and inited values).
while(cin.peek() != EOF && i < len)
{
cin >> arr[i];
++i;
}
You will want to do something after this to flush the buffer and not leave the rest of the line sitting on the input stream if you plan on doing other things with it.

Getting input from user using cin [duplicate]

This question already has answers here:
C++ "cin" only reads the first word [duplicate]
(5 answers)
Closed 4 years ago.
I am using Turbo C++ 3.0 Compiler
While using the following code ..
char *Name;
cin >> Name;
cout << Name;
When I gave input with space ... its only saving characters typed before space ..
like if I gave input "QWERT YUIOP" ... Name will contain "QWERT";
Any explaination why ??
When cin is used to read in strings, it automatically breaks at whitespace unless you specify otherwise.
std::string s;
std::cin >> noskipws >> s;
Alternatively, if you want to get a whole line then use:
std::getline(cin, s);
You'll also want to allocate storage for a raw char array, but with C++ you should use std::string or std::wstring anyway.
You need to allocate space for the char array into which you want to read the Name. char *Name; will not work as it only declares a char pointer not a char array. Something like char Name[30];
Also the cin << only allows us to enter one word into a string (char name[30]).
However, there is a cin function that reads text containing blanks.
cin.get(name, MAX)
get will read all characters including spaces until Max characters have
been read or the end of line character (ā€˜\nā€™) is reached and will put them
into the name variable.
You just declared a character pointer that doesn't point at anything. You need to allocate space for your string. The most common method would be to allocate space on the stack, IE:
char Name[50];
Remember a char pointer by itself is just a place to put an address to where the real memory is. You still have to get a block of memory and store the address in your pointer. The code above creates an array of Names on the stack and you can use Name to store up to 49 chars plus a null terminal.
Alternatively, for variable length strings use std::string.

C++ char* in methods

Listen people, i want to write a method that gets a line from the user, so i wrote this:
static char* getline(){
char temp[0];
cin >> temp;
return temp;
}
I also have a writeline method:
static void writeline(char* text){
cout<<text<<endl;
}
and then i go to the main and wrote this:
writeline(getline());
and it didnt work..
i want to say that when i wrote this:
static char* getline(){
char temp[0];
cin >> temp;
writeline(getline());
return temp;
}
and i wrote in main this:
getline();
it did work!
so what do i need to do?
There are a few things going on here.
First, you have to allocate memory when working with char*; a zero-length array won't be long enough. It's a lot easier to just use std::string which takes care of all the dirty work for you. Further, an array declared with a size in your function is allocated on the stack rather than the heap; once your getline function returns, the memory is no longer valid.
Second, the >> operator for strings reads the next word, not the next line. For that you need the getline method. Here comes the tricky thing: getline doesn't use std::string, so you still need the char*. You just don't want to return one, because then you need to deallocate it unless it's a global (or static) array. So, what you can do is the following:
std::string getline() {
char buf[1024]; // we have a cap on the line size
cin.getline(buf, 1024); // reads a line, up to 1023 characters
return std::string(buf); // makes a copy of buf into a properly-managed string
}
void writeline(const std::string &s) {
cout <<s <<endl;
}
Now you can do
writeline(readline());
and it should work fine. You can see here for more info on cin.getline().
There are two issues with your code.
First, you are trying to read a variable size input into a fixed-size array that is not a sufficient size - temp[0] may only be a single byte long. You are overruning the array and stomping on other data that is on the stack (like the return address.) This could cause a crash or odd behavior when the function returns.
Second, you are returning a local variable from a function. As soon as the function returns, the variable is out of scope and its stack space will be reused. You need to actually allocate memory if you are going to return it from a function.
The reason the second version works is that the stack-based array is still valid during the call to getline(), and since arrays grow downward getline() is immune to any stack corruption that was caused.
I think the problem is that your char temp[0] is defined inside the function (local to the function). Another problem i see is the temp[0], how many characters are you trying to allocate for the text input?
your returning corrupted memory, thats why
static char* getline(){
char temp[0];
cin >> temp;
return temp;
}
change this to
char temp[10000]; // put this outside in a class or global, give it some space
static char* getline(){
cin >> temp;
return temp;
}
There are a few things that are a bit suspect here.
First of all inside the getline() function you are declaring
char temp[0];
Which is an array of characters with no members. That can't possibly be what you intend.
Secondly your declaration of temp is as a variable on the stack. You can't use it as the return value of the function as it will go out of scope when you return.
Finally cin >> will only return a single character. Since your function is called getline I assume you want whole lines.
cin can do that for you using the getline function, but you need to pass it a buffer to put the line into.
See this reference:
http://www.cplusplus.com/reference/iostream/istream/getline/