Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Map Gives Bus Error when trying to set a value

I have the following function as the constructor for a class:

template<typename T>
void Pointer<T>::Pointer(T* inPtr)
{
  mPtr = inPtr;
  if (sRefCountMap.find(mPtr) == sRefCountMap.end()) {  
    sRefCountMap[mPtr] = 1;
  } else {
    sRefCountMap[mPtr]++;
  }
}

Here is the definition for the map:

static std::map<T*, int> sRefCountMap;

I get a Bus Error sometimes when this code is run:

#0  0x95110fc0 in std::_Rb_tree_decrement ()
#1  0x00017ccc in std::_Rb_tree_iterator<std::pair<Language::Value* const, int> >::operator-- (this=0xbfffe014) at stl_tree.h:196
#2  0x0001b16c in std::_Rb_tree<Language::Value*, std::pair<Language::Value* const, int>, std::_Select1st<std::pair<Language::Value* const, int> >, std::less<Language::Value*>, std::allocator<std::pair<Language::Value* const, int> > >::insert_unique (this=0x2a404, __v=@0xbfffe14c) at stl_tree.h:885
#3  0x0001b39c in std::_Rb_tree<Language::Value*, std::pair<Language::Value* const, int>, std::_Select1st<std::pair<Language::Value* const, int> >, std::less<Language::Value*>, std::allocator<std::pair<Language::Value* const, int> > >::insert_unique (this=0x2a404, __position={_M_node = 0x2a408}, __v=@0xbfffe14c) at stl_tree.h:905
#4  0x0001b5a0 in __gnu_norm::map<Language::Value*, int, std::less<Language::Value*>, std::allocator<std::pair<Language::Value* const, int> > >::insert (this=0x2a404, position={_M_node = 0x2a408}, __x=@0xbfffe14c) at stl_map.h:384
#5  0x0001b6e0 in __gnu_norm::map<Language::Value*, int, std::less<Language::Value*>, std::allocator<std::pair<Language::Value* const, int> > >::operator[] (this=0x2a404, __k=@0x2e110) at stl_map.h:339

Thanks.

like image 589
Maz Avatar asked Jun 29 '10 14:06

Maz


2 Answers

From your comments, you say that you're initialising a static Pointer. This most likely means you've encountered the "static initialisation order fiasco" - if two static objects are in different compilation units, then it's not defined which order they're initialised in. So if the constructor of one depends on the other already being initialised, then you might get away with it, or you might not. Sod's Law dictates that the code will work during testing, then mysteriously break when it's deployed.

The best solution is to avoid static objects; they're rarely a good idea.

Another possibility is lazy instantiation, something like this:

typedef std::map<T*, int> RefCountMap;

static RefCountMap& GetRefCountMap()
{
    static RefCountMap map;
    return map;
}

This may have issues of it's own; it's guaranteed to be constructed before it's used, but might be destroyed before you've finished with it, if a static destructor accesses it, and there may be thread safety issues. For the gory details, see the many discussions on the Singleton pattern, which requires a static instance. Singletons in C++ are a whole world of pain, best avoided if possible.

like image 56
Mike Seymour Avatar answered Sep 28 '22 23:09

Mike Seymour


You have likely corrupted your heap somewhere else in your program. Run your program through a memory debugger (e.g. valgrind) and figure out where the corruption is occurring.

like image 24
Tyler McHenry Avatar answered Sep 28 '22 23:09

Tyler McHenry