I am trying to sort a vector of smart pointers to a class. I use a struct as the third parameter to std::sort
with operator()
:
struct PhraseSmartPtrParseCreationComparer
{
bool operator()(const std::shared_ptr<Phrase>& a, const std::shared_ptr<Phrase>& b)
{
if (a.get() == nullptr)
return b.get() != nullptr;
if (b.get() == nullptr)
return a.get() != nullptr;
return *a < *b;
}
};
Once in a while, I get a segmentation fault where one of the pointers inside the comparing method points to an invalid structure; always one. The interesting bit is, just before the sort, all the objects are intact; I also tried modifying the function to remove the reference bit: const std::shared_ptr<Phrase> a
, and it crashed elsewhere.
The call is nothing fancy:
std::sort(_detectedPhrases.begin(), _detectedPhrases.end(), PhraseSmartPtrParseCreationComparer());
Is there something I'm missing or I should be looking elsewhere?
I can't believe how fast it was resolved. Here is the explanation - thank you for your guidance and cues, @BoBTFish and @Jabberwocky.
Indeed, the reason was that the sorter was having it both ways. The result was not symmetric. That is, the same two items, when swapped, could sometimes produce the same answer. Unfortunately, because of the business logic, it was actually valid. It's basically a tree, and one of the comparison components was whether one item is allowed to be a parent of the other - and a situation when both could theoretically be parents of the other is valid. So I did not change that. What I did (and hopefully it's not bad taste) was to add this workaround (never mind the nullptr
checks, they are not relevant):
struct PhraseSmartPtrParseCreationComparer
{
bool operator()(const std::shared_ptr<Phrase>& a, const std::shared_ptr<Phrase>& b)
{
return *a < *b && !(*b < *a);
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With