hash set crashing during iteration (boost 1.35.0)
Hello, I'm using boost 1.35.0 and found this sample code about the hash set functionality: http://www.boost.org/doc/libs/1_35_0/doc/html/intrusive/advanced_lookups_ins... and modified it as shown below. I find that when iterating through the hash table, the thing crashes here (where the get_next function contains an invalid value for n): template<class VoidPointer> struct slist_node_traits { .... static node_ptr get_next(const_node_ptr n) ----------> { return n->next_; } .... }; Should I use an earlier more stable version of boost or am I doing something dreadfully wrong? Thank you for any insights -Julie #include <stdio.h> #include <string> #include <iostream> // for std::cout #include <boost/foreach.hpp> #include <boost/intrusive/unordered_set.hpp> using namespace boost::intrusive; struct CStringHasher { std::size_t operator()(const std::string& str) const { std::size_t seed = 0; const char* sz = str.c_str(); if ( ! sz ) return seed; for(; *sz; ++sz) boost::hash_combine(seed, *sz); return seed; } }; class CWord : public unordered_set_base_hook<> { //This is a derivation hook public: std::string m_strWord; int m_nID; unordered_set_member_hook<> member_hook_; //This is a member hook CWord( const std::string& strWord, int nID ) : m_strWord( strWord ), m_nID( nID ) {} friend bool operator== (const CWord& a, const CWord& b) { return a.m_strWord == b.m_strWord; } friend std::size_t hash_value(const CWord& value) { return CStringHasher()(value.m_strWord.c_str()); } }; class CWordHash { public: typedef unordered_set<CWord> word_hash_set; typedef word_hash_set::bucket_type word_bucket_type; typedef word_hash_set::bucket_traits word_bucket_traits; typedef word_hash_set::iterator word_iter; CWordHash() : m_hWords( word_bucket_traits( m_Buckets, s_nNumBuckets ) ) {} ~CWordHash() { BOOST_FOREACH( CWord& w, m_hWords ) { CWord* pWord = &w; delete pWord; } } struct CStrExpensiveClassEqual { bool operator()(const std::string& str, const CWord &c) const { return str == c.m_strWord; } bool operator()(const CWord& c, const std::string& str) const { return str == c.m_strWord; } }; CWord* get( const std::string& str ) { word_iter it = m_hWords.find( str, CStringHasher(), CStrExpensiveClassEqual()); if( it == m_hWords.end() ) return NULL; return &*it; } bool insert( const std::string& strKey, int nID ) { word_hash_set::insert_commit_data insert_data; bool bSuccess = m_hWords.insert_check( strKey, CStringHasher(), CStrExpensiveClassEqual(), insert_data).second; if ( bSuccess ) { CWord* pWord = new CWord(strKey, nID); m_hWords.insert_commit(*pWord, insert_data); } return bSuccess; } static const int s_nNumBuckets = 10000; word_bucket_type m_Buckets[s_nNumBuckets]; word_hash_set m_hWords; }; extern int main(int argc, char *argv[]) { CWordHash hWords; // hash string to word id int nID = 1; std::string strWord = "hello"; hWords.insert( strWord, nID ); nID = 2; strWord = "world"; hWords.insert( strWord, nID ); for ( CWordHash::word_hash_set::iterator it = hWords.m_hWords.begin(); it != hWords.m_hWords.end(); it++ ) { CWord& w = *it; std::cout << w.m_strWord << "\t" << w.m_nID << "\n"; } return 0; }
AMDG Julie Larson wrote:
Hello,
I'm using boost 1.35.0 and found this sample code about the hash set functionality:
http://www.boost.org/doc/libs/1_35_0/doc/html/intrusive/advanced_lookups_ins...
and modified it as shown below. I find that when iterating through the hash table, the thing crashes here (where the get_next function contains an invalid value for n):
<snip> ~CWordHash() { BOOST_FOREACH( CWord& w, m_hWords ) { CWord* pWord = &w; delete pWord;
I think this delete invalidates the iterator maintained by BOOST_FOREACH. In Christ, Steven Watanabe
Thanks for the quick response Steven, However I think if you look at it you'll see that the destructor hasn't been called yet when the crash happens. The error happens during the iteration in main when trying to print out the contents of the word class. The destructor for the CWordHash class won't be called until after that when main exits. On Tue, May 13, 2008 at 9:17 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Julie Larson wrote:
Hello,
I'm using boost 1.35.0 and found this sample code about the hash set functionality:
http://www.boost.org/doc/libs/1_35_0/doc/html/intrusive/advanced_lookups_ins...
and modified it as shown below. I find that when iterating through the hash table, the thing crashes here (where the get_next function contains an invalid value for n):
<snip> ~CWordHash() { BOOST_FOREACH( CWord& w, m_hWords ) { CWord* pWord = &w; delete pWord;
I think this delete invalidates the iterator maintained by BOOST_FOREACH.
In Christ, Steven Watanabe
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
AMDG Julie Larson wrote:
Thanks for the quick response Steven, However I think if you look at it you'll see that the destructor hasn't been called yet when the crash happens. The error happens during the iteration in main when trying to print out the contents of the word class. The destructor for the CWordHash class won't be called until after that when main exits.
Using the trunk, it crashes in the destructor when the assertion on utilities.hpp line 394 { (void)hook; BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT(!hook.is_linked()); } I don't happen to have 1.35 available, though. In Christ, Steven Watanabe
Oh phooey, I wonder if this is a 64 bit issue. I should have mentioned that. I'm compiling for 64 bit address space, pointer sizes, etc., I think it actually might have something to do with that. Watching it in the debugger it gets into hashtable_node.hpp (boost::intrusive::detail::bucket_impl<Slist> during the iterator increment and comes back with a crazy number from this operation in (get_bucket_num): //Now just calculate the index b has in the bucket array return &b - &first_bucket; it is subtracting two addresses to arrive at the next bucket number and I think this is probably where my problem lies. Thank you -Julie On Tue, May 13, 2008 at 9:39 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Julie Larson wrote:
Thanks for the quick response Steven, However I think if you look at it you'll see that the destructor hasn't been called yet when the crash happens. The error happens during the iteration in main when trying to print out the contents of the word class. The destructor for the CWordHash class won't be called until after that when main exits.
Using the trunk, it crashes in the destructor when the assertion on utilities.hpp line 394
{ (void)hook; BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT(!hook.is_linked()); }
I don't happen to have 1.35 available, though.
In Christ, Steven Watanabe
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
AMDG Julie Larson wrote:
Oh phooey, I wonder if this is a 64 bit issue. I should have mentioned that. I'm compiling for 64 bit address space, pointer sizes, etc., I think it actually might have something to do with that.
Watching it in the debugger it gets into hashtable_node.hpp (boost::intrusive::detail::bucket_impl<Slist> during the iterator increment and comes back with a crazy number from this operation in (get_bucket_num):
//Now just calculate the index b has in the bucket array return &b - &first_bucket;
it is subtracting two addresses to arrive at the next bucket number and I think this is probably where my problem lies.
I suspect that this is a bug caused by the non-portable code in boost/units/detail/parent_from_member.hpp. In Christ, Steven Watanabe
Thanks. I'm glad I'm not crazy. =) On Wed, May 14, 2008 at 9:14 AM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Julie Larson wrote:
Oh phooey, I wonder if this is a 64 bit issue. I should have mentioned that. I'm compiling for 64 bit address space, pointer sizes, etc., I think it actually might have something to do with that.
Watching it in the debugger it gets into hashtable_node.hpp (boost::intrusive::detail::bucket_impl<Slist> during the iterator increment and comes back with a crazy number from this operation in (get_bucket_num):
//Now just calculate the index b has in the bucket array return &b - &first_bucket;
it is subtracting two addresses to arrive at the next bucket number and I think this is probably where my problem lies.
I suspect that this is a bug caused by the non-portable code in boost/units/detail/parent_from_member.hpp.
In Christ, Steven Watanabe
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Julie Larson wrote:
Hello,
I'm using boost 1.35.0 and found this sample code about the hash set functionality:
Sorry for being late. I just don't have time to read messages with no [intrusive] or [interprocess] in the subject ;-). Intrusive is being tested in 64 bit systems so there should not be problems. Give me some days to investigate the issue. Thanks to Steven for helping with this! Regards, Ion
Julie Larson wrote:
Hello,
I'm using boost 1.35.0 and found this sample code about the hash set functionality:
http://www.boost.org/doc/libs/1_35_0/doc/html/intrusive/advanced_lookups_ins...
and modified it as shown below. I find that when iterating through the hash table, the thing crashes here (where the get_next function contains an invalid value for n):
As Steven mentioned, executing this code:
BOOST_FOREACH( CWord& w, m_hWords ) { CWord* pWord = &w; delete pWord; }
in my windows (32 bit) machine raises an assertion (safe hook assertion) in the destructor of the hook (called by CWord's destructor) because you are deleting an object that is still inserted in an intrusive container. Since the container uses the hook to link objects, if we delete the object before erasing it from the container the container tries to access to unallocated memory. I know you get an error in another place, but just for information. Can you give me which compiler/platform are you using? Regards, Ion
participants (3)
-
Ion Gaztañaga
-
Julie Larson
-
Steven Watanabe