Mr. Llama
Mr. Llama

Reputation: 20889

Using string.erase() making a string longer?

I ran into this issue on accident while debugging a faulty string trim function and now I'm wondering what exactly is causing this behavior.

Here's a code snippet with just the relevant bits:

#include <iostream>
#include <string>
using namespace std;

void debug(string s) { cout << "Len: " << s.length() << "; Value: '" << s << "'" << endl; }

int main()
{
    string str = "ABC";
    debug(str);

    str.erase( str.begin() + 4, str.end() );  // Magic!
    debug(str):

    return 0;
}

You'll notice that the erase function is taking an iterator that starts just beyond the end of the string. This isn't the exact input used when I ran into the issue (it was having a +1 which broke empty strings), but it has a similar effect. Here's the output:

Len: 3; Value: 'ABC'
Len: 4; Value: 'ABC '

When I change the str.begin() + 4 to something greater like + 10 it becomes clear that I'm starting to pull in garbage data.

My question is: how is it that using the erase() function ends up making the string longer than before? Also, is it just luck, or is the next character after the end of the string always whitespace?

Upvotes: 2

Views: 105

Answers (3)

Michael Burr
Michael Burr

Reputation: 340188

string::erase() has the following precondition:

  • Requires: first and last are valid iterators on *this, defining a range [first,last)

since your code doesn't hold to this, it's exhibiting undefined behavior. There's not a whole lot of point in analyzing why it breaks something - basically the erase() function is making an assumption that's not true.

But if you're really curious about exactly what's going on you would at least need to specify which tool chain you're using (since UB varies quite a bit depending on the compiler and library). It would probably be easiest to just step through the code in a debugger to see why it's behaving this way in this instance.

Upvotes: 9

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361322

str.erase( str.begin() + 4, str.end() );  // Magic!

This invokes undefined behaviour, because str.begin()+4 points to beyond str.end(), as str.size() is 3.

That means, anything can happen : nothing is guaranteed by the language, nor by the compiler.

Upvotes: 2

James Kanze
James Kanze

Reputation: 153909

Passing invalid iterators is undefined behavior. Anything could happen.

Upvotes: 2

Related Questions