segmentation fault in following code

  • Thread starter Denis Petronenko
  • Start date
D

Denis Petronenko

Why do i have segmentaion fault after executing str.erase(it.base()) ?
compiler gcc 3.3.6.

string TrimRight(const string& strin)
{
string str = strin;
string::reverse_iterator it = str.rbegin();
while(it!=str.rend() && *it==' '){
str.erase(it.base());
it = str.rbegin();
}
return str;
}


int main()
{

string str = "hello ";
cout << str << "|"<< endl;
str = TrimRight(str);
cout << str << "|"<< endl;

return 0;
}
 
M

Mark P

Denis said:
Why do i have segmentaion fault after executing str.erase(it.base()) ?
compiler gcc 3.3.6.

string TrimRight(const string& strin)
{
string str = strin;
string::reverse_iterator it = str.rbegin();
while(it!=str.rend() && *it==' '){
str.erase(it.base());
it = str.rbegin();
}
return str;
}

IIRC, the base of rbegin() is end(). Then the first iteration of your
while loop is already a seg fault at erase.

Mark
 
F

F.J.K.

Mark said:
IIRC, the base of rbegin() is end(). Then the first iteration of your
while loop is already a seg fault at erase.

Out of my head, wouldn't that render reverse iterators completely
useless? Pretty much every algorithm has to begin() somewhere and if
every *rbegin() is an autosegfault, this functionality would be
completely unusable.

IIRC, for an int a[10] there are following equivalences

a.begin() == &a[0];
a.end() == &a[10];
a.rbegin() == &a[9];
a.rend() ==&a[-1]

pls correct me if I'm wrong (other than iterators not really being
pointers).
 
F

F.J.K.

F.J.K. said:
IIRC, for an int a[10] there are following equivalences

a.begin() == &a[0];
a.end() == &a[10];
a.rbegin() == &a[9];
a.rend() ==&a[-1]

pls correct me if I'm wrong (other than iterators not really being
pointers).

Ok, I am wrong and I correct myself ;-)

A reverse iterator contains a normal iterator current, so that
a.begin() == a.rend().current
a.end() == a.rbegin().current
As I already wrote, this would segfault all over the place (as indeed
the OP experiences). As a "clever solution" the STL implements the
*reverse_iterator operator to return *(current-1). The
reverse_operator.base() function however returns current directly,
which is the reason why above code (which doesn't compile btw.)
segfaults. The solution is obvious, only use reverse_iterator.base()-1.
The above example in its corrected form:

#include <iostream>
#include <string>
using namespace std;
string TrimRight(const string& strin)
{
string str = strin;
string::reverse_iterator it = str.rbegin();
while(it!=str.rend() && *it==' '){
str.erase(it.base()-1);
it = str.rbegin();
}
return str;
}

int main()
{

string str = "hello ";
cout << str << "|"<< endl;
str = TrimRight(str);
cout << str << "|"<< endl;

return 0;
}
 
H

Heinz Ozwirk

Denis Petronenko said:
Why do i have segmentaion fault after executing str.erase(it.base()) ?
compiler gcc 3.3.6.

string TrimRight(const string& strin)
{
string str = strin;
string::reverse_iterator it = str.rbegin();
while(it!=str.rend() && *it==' '){
str.erase(it.base());
it = str.rbegin();
}
return str;
}

Wouldn't

return strin.substr(0, strin.find_last_not_of(" ") + 1);

be much easier? You could also remove tabs and other whitespace with a
single statement.

Heinz
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top