4

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 in std::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!

oguz ismail
  • 1
  • 16
  • 47
  • 69
binary_jam
  • 63
  • 4
  • First of all, do the first example (using `std::getline` and `std::string`) work for long input? Have you checked other programs that take user input of arbitrary length? Or even just `echo "very long string here..."`? – Some programmer dude Aug 23 '21 at 18:08
  • 6
    The first step in diagnosing should be the status of the stream (.fail(), .bad()) and fgets, ferror returned values. – 273K Aug 23 '21 at 18:11
  • I think something is wrong with your environemnt: https://wandbox.org/permlink/GDJbd7DeQqFAxJvs – Ghasem Ramezani Aug 23 '21 at 18:12
  • 3
    *I read on the net that this might also be an issue with the buffer in terminal emulation itself.* That's exactly what you're running into. The terminal line editor limit on Solaris is set to 256 characters. See https://stackoverflow.com/questions/43749955/what-is-the-max-number-of-characters-read-command-can-take-in-one-line See also https://stackoverflow.com/questions/58100577/where-is-this-bash-line-length-limit-coming-from FWIW, on Linux it's 4096 characters. For Linux details: https://unix.stackexchange.com/questions/131105/how-to-read-over-4k-input-without-new-lines-on-a-terminal – Andrew Henle Aug 23 '21 at 19:01
  • First thing you should have done is type `cat` in your terminal, press enter, and go to town. – n. m. could be an AI Aug 23 '21 at 19:09
  • @S.M. I actually did that, just omitted it in the example code because it doesn't contribute to explaining the problem per se. I failed to list it in the "what I already did"-section though, that's right... – binary_jam Aug 23 '21 at 20:30
  • @AndrewHenle thanks a lot! that's actually a very good hint in the right direction... I will dig deeper into this! – binary_jam Aug 23 '21 at 20:35

0 Answers0