2012-02-22 46 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

相關問題