Reputation: 134
Firstly, there is somewhat a similar question asked here: Unusual std::map runtime error.
but since there is no real solution there, I would like ask it again, because I am really stuck and clueless.
My code is as follows:
struct MyObj{
//constructor
MyObj(){}
std::map<std::string, std::string> m_fooMap;
bool operator==(const MyObj& other)
{
if (m_fooMap.size() != other.m_fooMap.size())
return false;
std::map<std::string, std::string>::const_iterator i, j;
i = m_fooMap.cbegin();
j = other.m_fooMap.cbegin();
for (; i != m_fooMap.cend(), j != other.m_fooMap.cend(); ++i, ++j)
{
if(i->first.empty() || j->first.empty())
continue;
if (i->first != j->first)
return false;
if (i->second != j->second)
return false;
}
return true;
}
bool operator!=(const MyObj& other)
{
return !operator==(other);
}
};
struct AnotherObj{
std::map<std::string, MyObj> m_collectionOfObjs; //always guaranteed to contain atleast one entry
bool operator==(const AnotherObj &other) const
{
for (auto& objIt : m_collectionOfObjs)
{
auto findSeriesIt = other.m_collectionOfObjs.find(objIt.first);
if (findSeriesIt == other.m_collectionOfObjs.end())
return false;
//else found, see if the internal content is the same?
else
{
if (objIt.second != findSeriesIt->second)
return false;
}
}
//else
return true;
}
};
now, I have a std::vector anotherObjVec; And I need to compare the items inside this vector, with each other. for which I use the == operator.
Now at random instances everytime, even though the input data is the same, there seems to be a runtime error. The error points inside the "xtree" file, to the following code.
_Nodeptr _Lbound(const key_type& _Keyval) const
{ // find leftmost node not less than _Keyval
_Nodeptr _Pnode = _Root(); //<------------ THIS line is where it points to
_Nodeptr _Wherenode = this->_Myhead; // end() if search fails
while (!this->_Isnil(_Pnode))
if (_DEBUG_LT_PRED(this->_Getcomp(), this->_Key(_Pnode), _Keyval))
_Pnode = this->_Right(_Pnode); // descend right subtree
else
{ // _Pnode not less than _Keyval, remember it
_Wherenode = _Pnode;
_Pnode = this->_Left(_Pnode); // descend left subtree
}
return (_Wherenode); // return best remembered candidate
}
I am stuck and have no idea what to do next. I even tried initiating the constructor like this:
MyObj() : m_fooMap(std::map<std::string, std::string>()){}
Using C++11, Visual Studio 2012(v110)
Upvotes: 0
Views: 716
Reputation: 134
Turns out the map was not instantiated correctly. This happened to me because I was using std::shared_ptr and storing it in a std::vector. Then iterating over it, one of shared ptrs was a nullptr. No idea why that happened, because it is a shared ptr and it being in the vector should still keep a reference count up, but I just changed the iteration technique over the vector and it works now.
Upvotes: 0
Reputation: 20969
Your words
even though the input data is the same, there seems to be a runtime error.
so it looks that operator==
should return true at the end of block, but your function doesn't return any value (if your maps are empty your functions reaches the end of block where there is no return statement):
bool operator==(const MyObj& other)
{
if (m_fooMap.size() != other.m_fooMap.size())
return false;
std::map<std::string, std::string>::const_iterator i, j;
i = m_fooMap.cbegin();
j = other.m_fooMap.cbegin();
for (; i != m_fooMap.cend(), j != other.m_fooMap.cend(); ++i, ++j)
{
if(i->first.empty() || j->first.empty())
continue;
if (i->first != j->first)
return false;
if (i->second != j->second)
return false;
}
// ??? return is missing here
}
so it is undefined behaviour
(from):
Flowing off the end of a value-returning function (except main) without a return statement is undefined behavior.
Upvotes: 1
Reputation: 60787
You're comparing iterators from different maps:
auto findSeriesIt = other.m_collectionOfObjs.find(objIt.first);
if (findSeriesIt == m_collectionOfObjs.end())
return false;
findSeriesIt
is from the other.m_collectionOfObjs
map but you're comparing it to the end of m_collectionOfObjs
. It should be:
auto findSeriesIt = other.m_collectionOfObjs.find(objIt.first);
if (findSeriesIt == other.m_collectionOfObjs.end())
return false;
Upvotes: 1
Reputation: 37599
i != m_fooMap.cend(), j != other.m_fooMap.cend()
uses comma operator, discarding first operand. It does not check both conditions so when i
is equal to end iterator it may be later dereferenced. You should use and
operator instead:
(m_fooMap.cend() != i) and (other.m_fooMap.cend() != j);
Upvotes: 0