c ++ map <string,string> :: find似乎返回垃圾迭代器</string,string>

时间:2012-02-22 10:40:18

标签: c++

map<string,string>::find似乎正在返回垃圾迭代器,因为我既不能访问my_it->first也不能访问第二个(NB:my_it != my_map.end()已经过验证)。 VC2010报告调试错误,并深入了解

my_it is (Bad Ptr, Bad Ptr).

'违规'地图是一个类属性_match,如下所示:

class NicePCREMatch
{
private:
    map<string, string, less<string> > _match;

public:
    void addGroup(const string& group_name, const string& value);
    string group(const string& group_name);
};

以下是按键返回元素的代码(注释掉的代码可以正常工作):

string NicePCREMatch::group(const string& group_name)
{
    /*for (map<string, string, less<string> >::iterator j = _match.begin(); j != _match.end(); j++)
    {
        if(!strcmp(j->first.c_str(), group_name.c_str()))
        {
            return j->second;
        }
    }

    throw runtime_error("runtime_error: no such group");*/

    map<string, string, less<string> >::iterator i = _match.find(group_name);

    if (i == _match.end())
    {
        throw runtime_error("runtime_error: no such group");
    }

    return i->second;
}

以下是在地图中插入新元素的代码:

void NicePCREMatch::addGroup(const string& group_name, const string& value)
{
    _match.insert(pair<string, string>(group_name, value));
}

另一个类使用NicePCREMatch如下:

template<class Match_t>
vector<Match_t> NicePCRE<Match_t>::match(const string& buf)
{
[snip]
    Match_t m;
[snip]
    m.addGroup(std::string((const char *)tabptr + 2, name_entry_size - 3), \
                buf.substr(ovector[2*n], ovector[2*n+1] - ovector[2*n]));
[snip]
    addMatch(m);
[snip]
    return _matches;
}

其中,

template<class Match_t>
void NicePCRE<Match_t>::addMatch(const Match_t& m) 
{ 
    _matches.push_back(m);
}

最后,客户端代码使用NicePCRE类,如下所示:

void test_NicePCRE_email_match(void)
{
    NicePCRE<> npcre;
    npcre.compile("(?P<username>[a-zA-Z]+?)(?:%40|@)(?P<domain>[a-zA-Z]+\.[a-zA-Z]{2,6})");
    vector<NicePCREMatch> matches = npcre.match("toto@yahoo.com");
    assert(!matches.empty());
    assert(!strcmp(matches.begin()->group("username").c_str(), "toto"));
    cout << matches.begin()->group("domain").c_str() << endl;
    assert(!strcmp(matches.begin()->group("domain").c_str(), "yahoo.com"));
}
顺便说一下,这 - 几乎是 - 我的主要(有史以来最奇怪的TDD :)):

int main()
{
    int test_cnt = 0;
    cout << "Running test #" << test_cnt << " .." << endl;
    test_NicePCRE_email_match();
    cout << "OK." << endl << endl;
    test_cnt++;

    SleepEx(5000, 1);

    return 0;
}

我在这里做错了什么?

修改 以下修改(与上面的版本比较)解决了我的问题。即,

void NicePCREMatch::addGroup(const string& group_name, const string& value)
{
    _match.insert(pair<string, string>(group_name.c_str(), value.c_str()));
}

客户端代码(稍加修改)现在看起来像这样:

void test_NicePCRE_email_match(void)
{
    NicePCRE<> npcre;
    npcre.compile("(?P<username>[a-zA-Z]+?)(?:%40|@)(?P<domain>[a-zA-Z]+\.[a-zA-Z]{2,6})");
    vector<NicePCREMatch> matches = npcre.match("toto@yahoo.com");
    assert(!matches.empty());
    try
    {
        assert(!strcmp(matches.begin()->group("username").c_str(), "toto"));
        assert(!strcmp(matches.begin()->group("domain").c_str(), "yahoo.com"));
        cout << "username = " << matches.begin()->group("username") << endl;
        cout << "domain = " << matches.begin()->group("domain") << endl;
    }
    catch (const runtime_error& e)
    {
        cout << "Caught: " << e.what() << endl;
        assert(0x0);
    }
}

这很奇怪。有人可以解释一下。但是,我认为我的问题已经解决了。

谢谢大家。

2 个答案:

答案 0 :(得分:0)

这可能是由三件事引起的 - 要么在执行find之后以某种方式修改映射,要么在程序中某处存在内存损坏,或者调试器根本没有显示迭代器的正确值。

尝试使用调试输出 - 如果在尝试输出值时代码崩溃,那么迭代器可能真的坏了。

另外,请确保在执行find后不修改地图。如果这样做,这可能会使迭代器无效,因此您需要在使用迭代器之前立即移动find调用。

如果上述两个选项都无法帮助您,可能会在某处出现内存损坏,您需要找到它。也许可以使用valgrind。请注意,只有当证明其他两个选项不可能时,这应该是你的最后手段。

答案 1 :(得分:0)

您的问题在这里

if (i == _match.end())
{
    throw runtime_error("runtime_error: no such group");
}

return i->second;

你的发现由于某种原因失败了。我不能说为什么,因为我没有完整的代码。但是,在失败之后,你正在抛出一个错误,但是没有人可以赶到外面。请在调用方法组()的位置添加try catch,并在未找到匹配时实现逻辑。 我尝试使用你的示例代码片段(+一些更改来编译这些东西),看起来visual studio继续使用函数中的下一行,即使在throw语句之后也是如此。我不知道背后的理论。看到这样的行为,我有点意外。

[为了确保您的类结构不会导致问题,我尝试使用简单的全局方法,甚至该方法也给了我相同的行为。如果有人可以解释这个,请随意。]