The Problem
I am working with a small command line utility that reads user input, computes stuff and outputs the results. Now there's a problem when the user inputs more than 256 characters in a single line - and I can't get my head around why that is...
Example Code
Here's three variations of example code I tried - all of them yield the same result. It basically only reads a line of text from the command prompt and puts out the length of the text plus the text itself.
Example 1, using std::getline
:
int main(int argc, char**argv)
{
std::string mystr;
std::cout << "Enter your stuff: ";
std::getline(std::cin, mystr);
std::cout << "len: " << mystr.size() << std::endl;
std::cout << "cnt: " << mystr << std::endl;
}
Example 2, using std::basic_istream::getline
:
int main(int argc, char**argv)
{
char mybuf[8192];
std::cout << "Enter your stuff: ";
std::cin.getline(mybuf, 8192);
std::cout << "len: " << strlen(mybuf) << std::endl;
std::cout << "cnt: " << mybuf << std::endl;
}
Example 3, using fgets
:
int main(int argc, char**argv)
{
char mybuf[8192];
std::cout << "Enter your stuff: ";
fgets(mybuf, 8192, stdin);
std::cout << "len: " << strlen(mybuf) << std::endl;
std::cout << "cnt: " << mybuf << std::endl;
}
Test Cases
Now, if I start that code and put in some relatively short text, it works like expected up until 256 characters of input:
Enter your stuff: Labore fugit nostrum maxime doloremque tempore. Numquam et aut qui possimus assumenda ut. Et aut minima nisi assumenda enim. Aut perspiciatis quasi non distinctio facilis tempora quam. Mollitia quibusdam nam et ipsa quo ex nulla. Aut iste vel at iure est u
len: 256
cnt: Labore fugit nostrum maxime doloremque tempore. Numquam et aut qui possimus assumenda ut. Et aut minima nisi assumenda enim. Aut perspiciatis quasi non distinctio facilis tempora quam. Mollitia quibusdam nam et ipsa quo ex nulla. Aut iste vel at iure est u
When entering exactly 257 bytes, the getline/fgets call reads nothing?
Enter your stuff: Labore fugit nostrum maxime doloremque tempore. Numquam et aut qui possimus assumenda ut. Et aut minima nisi assumenda enim. Aut perspiciatis quasi non distinctio facilis tempora quam. Mollitia quibusdam nam et ipsa quo ex nulla. Aut iste vel at iure est ut
len: 0
cnt:
And then, if you keep entering more data it acts like it would reset the buffer (index) and fill it again from the start at byte 258:
Enter your stuff: Labore fugit nostrum maxime doloremque tempore. Numquam et aut qui possimus assumenda ut. Et aut minima nisi assumenda enim. Aut perspiciatis quasi non distinctio facilis tempora quam. Mollitia quibusdam nam et ipsa quo ex nulla. Aut iste vel at iure est ut in. Alias dolore enim magnam. Quia quam libero quae.
len: 53
cnt: in. Alias dolore enim magnam. Quia quam libero quae.
Some More Info
What I did so far:
- checked the
string::max_size()
, which is used instd::getline
. It returns 1073741820. - tried different ssh clients (no X on the target machine, only ssh) on different OSes.
- changed the buffer size to 4K with
std::setvbuf
This is the environment:
- OS: Oracle Solaris 11.4
- Compiler: GCC 4.9.4
- Shell: Bash 5.0.17
Questions
Why the heck is it acting like this? I know I could just read the data from a file, but this functionality is needed in a small tool for users/administrators. Having the user fill a file first would be a rather unnecessary additional step.
I read on the net that this might also be an issue with the buffer in terminal emulation itself. Any ideas how I could check or influence that? My searches didn't come up with any useful information. Maybe I'm also just missing the correct keywords...
Thanks for any thoughts you might have!