thebator
thebator

Reputation: 115

String::erase throws length_error when using it with iterator

stringstream str(line, ios_base::in);
while(!str.eof()){
    string word;
    str >> word;
    std::transform(word.begin(), word.end(), word.begin(), ::tolower);
    char c = *(--word.end());
    char b = *word.begin();
    if((c == ')' && b == '(') || (c == '\'' && b == '\'')){
        word.erase(--word.end());
        word.erase(word.begin()); //exception occurs here
    }
    c = *(--word.end());
    if(c == ',' || c == '.' || c == '?' || c == '!')
        word.erase(--word.end());
}

This code throws an std::length_error (what(): basic_string::_S_create) at word.erase(word.begin()); however if I change it to word.erase(0, 1); it works perfectly fine.

Why is that?

I am using gcc 4.8.1 (MinGW build)

Upvotes: 0

Views: 151

Answers (2)

Dietmar Kühl
Dietmar Kühl

Reputation: 153810

There are multiple things wrong with your code:

  1. You should always check that extraction from a stream was successful after trying to read fro the stream.
  2. Using std::istream::eof() to terminate a loop does not work. You might want to use eof() to decide whether you want to report an error.
  3. Using std::tolower() with chars on a platform where char is signed result in undefined behavior, e.g., for most encodings it will result in undefined behavior when using it with my last name.
  4. When the word is empty all kinds of strange things can happen. Since you didn't check if you could successfully read a word, I guess this is what happens: erase() the position begin() points to when using it on a empty string will fail.

Upvotes: 2

kennytm
kennytm

Reputation: 523214

If the line consists of a single character

'

then

  • the condition (c == '\'' && b == '\'') will pass, so we'll start to delete the beginning and end characters,
  • word.erase(--word.end()); will remove the only character, making the string empty,
  • and then word.erase(word.begin()); will crash, because word.begin() now doesn't point to a valid character in the string. (I think it actually causes undefined behavior)

Upvotes: 2

Related Questions