简体   繁体   中英

string::replace throws std::out_of_range on valid iterators

Really can't figure out the reason for 'terminate called after throwing an instance of 'std::out_of_range''

std::cerr << std::string(s[0].first, s[0].second) << std::endl;
std::cerr << std::string(e[0].first, e[0].second) << std::endl;
std::cerr << std::string(s[0].first, e[0].second) << std::endl;

the above code return valid strings with matched results

    boost::regex start(elementStartTag);
    boost::regex end(elementEndTag);

    boost::match_results<std::string::const_iterator> s, e;

    if(!boost::regex_search(tmpTemplate, s, start)) {
        dDebug() << "No start token: " << elementStartTag << " was found in file: " << templatePath();
        std::cerr << "No start token: " << elementStartTag << " was found in file: " << templatePath() << std::endl;
        return;
    }

    if(!boost::regex_search(tmpTemplate, e, end)) {
        dDebug() << "No end token: " << elementEndTag << " was found in file: " << templatePath();
        std::cerr << "No end token: " << elementEndTag << " was found in file: " << templatePath() << std::endl;
        return;
    }

    //std::string::iterator si, ei;
    //        si = fromConst(tmpTemplate.begin(), s[0].second);
    //        ei = fromConst(tmpTemplate.begin(), e[0].first);

    //        std::cerr << std::string(si, ei) << "\t" << ss.str(); // return valid string

    std::cerr << std::string(s[0].first, s[0].second) << std::endl;
    std::cerr << std::string(e[0].first, e[0].second) << std::endl;
    std::cerr << std::string(s[0].first, e[0].second) << std::endl;


    std::cerr << "s[0].first - tmpTemplate.begin()\t" << s[0].first - tmpTemplate.begin() << std::endl;
    std::cerr << "s[0].first - e[0].second\t" << s[0].first - e[0].second << std::endl;

    //tmpTemplate.replace(fi, se, ss.str()); //also throws exeption
    tmpTemplate.replace(s[0].first - tmpTemplate.begin(), s[0].first - e[0].second, "test"); // throws exeption

gcc version: 4.7.3 if it really matters

boost version: 1.52.0

UPDATE:

First: The following equation is wrong s[0].first - e[0].second should be e[0].second - s[0].first - i wonder why nobody saw this (me also) - but consider it a typo, cause s[0].first - tmpTemplate.begin() return negative number anyway.

tmpTemplate defined and initialized as

  std::string tmpTemplate= getTemplate();

Great - as i said s[0].first - tmpTemplate.begin() returns negative number

if tmpTemplate is defined and initialized as

std::string tmpTemplate(getTemplate().data(), getTemplate().length());

everything is fine.

Second:

stop boost::match_results uninitialized nonsense please read the regex_search documentation it says: "If i find no match i return false"

Third:

std::string tmpTemplate= getTemplate();

and

std::string tmpTemplate(getTemplate().data(), getTemplate().length());

DOES REALLY DIFFER.

Own Сonclusion:

It is ether a memory corruption which occurs else where in my code and i can't detect it with valgrind, or a bug which is not part of my code.

What are the contents of tmpTemplate , elementStartTag and elementEndTag ? If the elementEndTag precedes the elementStartTag in tmpTemplate , then you'll definitely get an out_of_range error.

In the end, I'd recommend using just one regular expression, along the lines of:

boost::regex matcher( ".*(" + elementStartTag + ")(.*)(" + elementEndTag + ").*");

and then using boost::regex_match rather than search. This guarantees the order; it may cause problems if there is more than one matching element in the sequence, however. If this is an issue: you should use:

boost::regex_search( s[1].second, tmpTemplate.end(), e, end )

as the expression for matching the end.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM