Thread: Why would ifstream::getline hang and not return?

  1. #1
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827

    Why would ifstream::getline hang and not return?

    I encountered a situation where istream::getline() hangs, and does not return.
    Why would this be?

    Code:
    bool CfileOperations::readLine(char buffer[], streamsize bufferSize) {
    
        filestreamInObject.getline(buffer, bufferSize);
        if (filestreamInObject.good()) { //no error flags set
            return true;
        }
    
        else {
            return false;
        }
    
    }
    filestreamInObject is an object of ifstream.
    Last edited by Programmer_P; 07-16-2010 at 07:34 AM.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  2. #2
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Quote Originally Posted by Programmer_P View Post
    I encountered a situation where istream::getline() hangs, and does not return.
    Why would this be?
    this is typically called blocking, and it happens when the stream cannot find an end-of-line character. In a file it should return when it fills the buffer or reaches the end of the file, so this seems pretty strange to me. is it possible you're overrunning the end of your buffer? that can cause strange behavior.

  3. #3
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Elkvis View Post
    this is typically called blocking, and it happens when the stream cannot find an end-of-line character. In a file it should return when it fills the buffer or reaches the end of the file, so this seems pretty strange to me. is it possible you're overrunning the end of your buffer? that can cause strange behavior.
    Hmm...yeah, the buffer must have been too small. I was using a char array with 100 elements as the buffer, because I didn't think there would a line longer than that in a file, but I ran it on a source file of mine for my web coder program, and there must have been some line with more than 100 characters. Once I changed the array size to 200, its no longer hanging. But why would getline overrun the end of the buffer? I passed to it the sizeof the array, which was 100, so I don't see why it would overrun the end of the buffer...

    Thanks for the reply.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    How exactly is the caller supposed to know the length of the line in the file they are grabbing without first reading in the line in the file? This seems like a dangerous function. Try using std::getline to avoid having to specify the buffer size which the caller probably would not know and which your function has no way of checking if the line in the file is actually the specified size.
    Last edited by VirtualAce; 07-17-2010 at 10:59 AM.

  5. #5
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Bubba View Post
    How exactly is the caller supposed to know the length of the line in the file they are grabbing without first reading in the line in the file? This seems like a dangerous function. Try using std::getline to avoid having to specify the buffer size which the caller probably would not know and which your function has no way of checking if the line in the file is actually the specified size.
    The caller doesn't need to know the length of the line. It only needs to know the size of the buffer array which will store the inputted line read by getline(). And that is easily achieved by passing sizeof(array) to the second parameter of the readLine() function, which is what I do.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Programmer_P
    Hmm...yeah, the buffer must have been too small. I was using a char array with 100 elements as the buffer, because I didn't think there would a line longer than that in a file, but I ran it on a source file of mine for my web coder program, and there must have been some line with more than 100 characters. Once I changed the array size to 200, its no longer hanging. But why would getline overrun the end of the buffer? I passed to it the sizeof the array, which was 100, so I don't see why it would overrun the end of the buffer...
    What is the code that calls CfileOperations::readLine? It is possible that when your assumption that the length of a line would not exceed 99 characters failed, a corresponding necessary assumption in that code no longer held true, and thus it is that code that "hangs".

    Quote Originally Posted by Programmer_P
    The caller doesn't need to know the length of the line. It only needs to know the size of the buffer array which will store the inputted line read by getline(). And that is easily achieved by passing sizeof(buffer) to the second parameter of the readLine() function.
    It depends on what you are trying to do. If you are trying to read each line of the file in its entirety into the buffer, then knowing the size of the buffer is not enough. You need to know the length of the longest line in the file. Of course, the code should still be well behaved if there is a line that is too long, but then it would not be guaranteed (by you) to work as specified under normal conditions.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by laserlight View Post
    What is the code that calls CfileOperations::readLine?
    I basically just pass to it at every call a char array with 100 elements (0 - 99), and sizeof(array), storing the return value of the function in a bool variable. If that bool variable is true after the call, then I proceed to do operations with the line read from.
    It is possible that when your assumption that the length of a line would not exceed 99 characters failed, a corresponding necessary assumption in that code no longer held true, and thus it is that code that "hangs".
    Nope. That's not correct.
    I know for a fact that it was getline() that caused the hang, because that's what my debugger pointed me to.
    It depends on what you are trying to do. If you are trying to read each line of the file in its entirety into the buffer, then knowing the size of the buffer is not enough. You need to know the length of the longest line in the file. Of course, the code should still be well behaved if there is a line that is too long, but then it would not be guaranteed (by you) to work as specified under normal conditions.
    Not really. If I ensure that the buffer is big enough to handle most any normal line, then I do not need to know the length of the lines. I mean...seriously, who would have any line in a file with more than 200 characters?
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Programmer_P
    I know for a fact that it was getline() that caused the hang, because that's what my debugger pointed me to.
    If that is true, then you have found a standard library implementation bug. What is your compiler? Are you using its default standard library implementation?

    I checked the text of C++03: if that version of getline reads (and stores) the line without encountering end of file or the delimiter, it should set the failbit. Therefore, CfileOperations::readLine should have returned false.

    But before we jump to the conclusion that you have found an implementation bug, show us the smallest and simplest compilable program that demonstrates the "hanging".

    Quote Originally Posted by Programmer_P
    If I ensure that the buffer is big enough to handle most any normal line, then I do not need to know the length of the line.
    In other words, you are specifying the maximum length of a line for normal operation.

    Quote Originally Posted by Programmer_P
    I mean...seriously, who would have any line in a file with more than 200 characters?
    I mean...seriously, who would have any line in a file with more than 100 characters?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    why not use std::getline() instead? if you use std::getline() and std::string, you would never have to worry about the length of the lines.

  10. #10
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by laserlight View Post
    If that is true, then you have found a standard library implementation bug. What is your compiler? Are you using its default standard library implementation?
    My compiler is GCC. My IDE is Code::Blocks.
    Standards - Using the GNU Compiler Collection (GCC)
    GCC supports the ISO C++ standard (1998) and contains experimental support for the upcoming ISO C++ standard (200x).
    I checked the text of C++03: if that version of getline reads (and stores) the line without encountering end of file or the delimiter, it should set the failbit. Therefore, CfileOperations::readLine should have returned false.
    Well, it didn't...
    But before we jump to the conclusion that you have found an implementation bug, show us the smallest and simplest compilable program that demonstrates the "hanging".
    I will. Give me a little while to do this though.
    In other words, you are specifying the maximum length of a line for normal operation.


    I mean...seriously, who would have any line in a file with more than 100 characters?
    That's different. I increased the maximum by 100 and I'm pretty sure no one will have a line that comes even close to that. If I encounter such a situation though, I could always increase the maximum again.
    Last edited by Programmer_P; 07-17-2010 at 12:29 PM.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Programmer_P
    My compiler is GCC.
    What is the exact version number, and what is the operating system?

    Quote Originally Posted by Programmer_P
    I increased the maximum by 100 and I'm pretty sure no one will have a line that comes nearly as close as that. If I encounter such a situation, I could always increase the maximum again.
    Logically, you cannot know of that situation until after your program is in use, in which case changing the maximum means going through the process of editing, compiling, linking, testing and distribution. Using std::string with the corresponding version of getline would mean that you do not need to do that. But if you insist, then a correct thing to do is to gracefully treat as an error a case where the line encountered is too long for the buffer (of course, you need an implementation of getline that is not broken). Alternatively, you use a dynamic array for the buffer, and basically handle the process of expanding the buffer yourself (i.e., your use of getline would become more complicated), but when std::string and such is available, that is just silly unless you have other important considerations.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by laserlight View Post
    What is the exact version number, and what is the operating system?
    0.99
    Ubuntu 8.10 64 bit.
    Logically, you cannot know of that situation until after your program is in use, in which case changing the maximum means going through the process of editing, compiling, linking, testing and distribution. Using std::string with the corresponding version of getline would mean that you do not need to do that. But if you insist, then a correct thing to do is to gracefully treat as an error a case where the line encountered is too long for the buffer (of course, you need an implementation of getline that is not broken). Alternatively, you use a dynamic array for the buffer, and basically handle the process of expanding the buffer yourself (i.e., your use of getline would become more complicated), but when std::string and such is available, that is just silly unless you have other important considerations.
    You're right, and I'm already changing the code to use std::getline as we speak. Thanks for that suggestion, elkvis.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Programmer_P
    I will. Give me a little while to do this though.
    Incidentally, I am talking about something as simple as this:
    Code:
    #include <iostream>
    
    int main()
    {
        char buffer[100];
        std::cin.getline(buffer, sizeof(buffer));
        std::cout << "reached" << std::endl;
    }
    You may be able to prove that a bug exists in the implementation of getline using the above program by simply entering 100 characters (or more) on standard input and watching as "reached" is never printed. (EDIT: on the other hand, maybe not. If there was a buffer overflow, the effects could become much more difficult to predict, hence the need for you to come up with the program.)

    Quote Originally Posted by Programmer_P
    0.99
    hmm... that seems unlikely: such a version, if it ever existed, would be terribly ancient. Distrowatch shows that the version of GCC that should come by default on Ubuntu 8.10 is 4.3.1.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    You're right, and I'm already changing the code to use std::getline as we speak. Thanks for that suggestion, elkvis.
    Try using std::getline to avoid having to specify the buffer size which the caller probably would not know and which your function has no way of checking if the line in the file is actually the specified size.
    My original suggestion way back when.

  15. #15
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by laserlight View Post
    hmm... that seems unlikely: such a version, if it ever existed, would be terribly ancient. Distrowatch shows that the version of GCC that should come by default on Ubuntu 8.10 is 4.3.1.
    Well, I think another version of GCC ships with Code::Blocks, and that's the one used by the IDE. Of course I could be wrong though.
    Anyway, I got the version number by going to the Help menu, selecting Plugins>Compiler..., and then in the dialog that pops up, going to the "Information" tab, and it says the version number there.

    EDIT: Fixed. It uses std::getline() now, so I wont bother posting any code.
    Last edited by Programmer_P; 07-17-2010 at 01:27 PM.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

Popular pages Recent additions subscribe to a feed