2012-02-22 43 views
2

map<string,string>::find似乎是返回垃圾迭代器,因为我既不能访问my_it->first也不能访问第二个(注意:my_it != my_map.end()已验证)。 VC2010报告调试错误,并寻求更深层次的揭示C++ map <string,string> :: find似乎返回垃圾迭代器

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("[email protected]"); 
    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("[email protected]"); 
    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); 
    } 
} 

这是很奇怪的。有人可以请解释。不过,我认为我的问题已经解决了。

感谢每一位。

+0

是否有可能'_match'被另一个线程同时修改?这种错误也可能是由于线程中其他地方的内存破坏导致的。 – 2012-02-22 10:46:01

+0

感谢代理比约恩波利斯。不,只有一个线程才能访问_match映射。顺便说一句,如果它是由于其他线程(或一些其他线程不安全的东西)的内存腐败,我怎么解释注释掉的代码工作,但没有与地图::查找调用?)。 – dohmatob 2012-02-22 11:00:51

+0

'map >'比较规范('less ''')需要什么? – 2012-02-22 11:01:11

回答

0

你的问题就在这里

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

return i->second; 

您发现由于某种原因失败。我不能说为什么,因为我没有完整的代码。但是,在失败之后,你会抛出一个错误,但没有人能够追到外面。请在您调用方法组()的位置添加try catch,并在未找到匹配的情况下实施逻辑。 我试着用你的示例代码片段(+一些更改来获得编译的东西),它看起来像Visual Studio继续在函数中的下一行,即使在一个throw语句后。我不知道它背后的理论。看到这样的行为让我有点惊讶。

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

+0

嗨Unni。 - 事实上'runtime_error(“runtime_error:no such group”)'在类方法'string NicePCREMatch :: group'中被抛出,但是没有被我的'void test_NicePCRE_email_match''测试用例'捕获。但是,由于一些奇怪的原因VS2010没有报告runtime_error这样(它会给我错误的错误PTR错误的东西)。我在void'test_NicePCRE_email_match'中尝试捕获逻辑,并捕获了runtime_error(“runtime_error:no such group”)''。 - 我对我的(未显示)载体有信心 NicePCRE ::匹配启发式,为什么find(..)失败?答案在我的编辑中。谢谢 – dohmatob 2012-02-22 15:42:06

+0

你是说,在改变“_match.insert(pair (group_name.c_str(),value.c_str()));”发现开始给一个有效的迭代器? – PermanentGuest 2012-02-22 15:58:10

+0

再次感谢@Unni。顺便说一句,有人点击/投票吗?为什么?或者我在这里错过了什么?如果是的话,我希望我有足够的声誉来立即撤销它。 – dohmatob 2012-02-22 16:00:00

0

这可能是由三件事情引起的 - 无论是在执行find之后以某种方式修改映射,还是程序某处存在内存损坏,或者调试器无法为迭代器显示正确的值。

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

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

如果上述两个选项都无助于您在某处可能出现内存损坏,并且您需要找到它。也许使用valgrind。请注意,只有当其他两个选项不可行时,这应该是您的最后一招。

+4

'valgrind'应该**不是**你的“最后的手段”。 _离得很远_。 – 2012-02-22 11:11:54

+0

我的意思是说它需要很大的努力来运行,而不是它不会完成这项工作。检查我们是否有案例1或案例2会花更少的时间,这就是为什么我说你只有在排除了其他选项后才应该使用valgrind。 – 2012-02-22 11:28:09

+0

这是无稽之谈。 '$ valgrind myApp'确实很容易输入,你应该在开发过程中做这件事情_anyway_;它的效率和效率要比花费半天的时间在整个代码中分散调试行,然后晚上分析它们的输出更有效率和有效。 – 2012-02-22 11:38:03

相关问题