5
struct Object
{
    int x;
    int y;
    bool isXValid()
    {
       return x > 0;
    }
};

bool mySort(const Object& lhs, const Object& rhs)
{
    // Note the short-circuit here
    bool isValidForCheck = lhs.isXValid() && rhs.isXValid();

    // rhs may be valid because short-circuit, or both may be invalid
    if (isValidForCheck)
    {
       return lhs.x < rhs.x;
    }

    return lhs.y < rhs.y;
}

int main()
{
    std::vector<Object> myVec;
    // random populating of myVec
    std::sort(myVec.begin(), myVec.end(), mySort);
    return 0;
}

My comparison function is irreflexive but does not respect transitivity.

stl ordering - strict weak ordering

Thus, if:

  (a < b) == true, (b < a) must be false.

Additionally, if:

   a == b, then (a < b) and (b < a) are false.

However, it is not transitive. For example, with the following values:

 (1, 3) (-1, 2), (3, 1)

Then it is possible to produce a sorted container where:

  a < b, and b < c, but c < a.

This answer : What causes std::sort() to access address out of range explains why std::sort will address out-of-bounds when the comparison function doesn't respect irreflexibility (for example, quicksort where we do comp(pivot, pivot) and get true, thus the left pointer keeps walking right off the end of the array).

However, I am seeing crashes with comparisons that are irreflexive but non-transitive. I also believe I am going off the end of the array.

I cannot provide the exact code here as it is proprietary. The example above will not crash in my tests, but I am aware that std::sort will select different algorithms based upon the container and elements to be sorted.

What I'd like to know is if anybody knows why std::sort would crash under GNU C++ when the comparison is non-transitive? I know that non-transitive comparisons break the contract and it's undefined behaviour, but I was hoping for a similar answer to the one in the linked question - i.e. precisely why it can crash.

Mike B
  • 478
  • 2
  • 11
  • 8
    Where would you put `c` if `a < b` and `b < c` but `c < a`? – NathanOliver Aug 09 '17 at 19:57
  • 2
    "i.e. precisely why it can crash." There are many possible implementations of `std::sort`. Only what is in common - they must follow specifications. So you question is - what is possible (future) implementation that can crash on this particular violation. Do not you think you are asking for too match? – Slava Aug 09 '17 at 20:08
  • @NathanOliver I believe this will depend entirely on the order of the initial input and the sorting algorithm chosen. I've done a few scratch-pad paper approaches and found that the 'invalid' elements will often naturally gravitate to the top or bottom of the array, or they may end up in the middle. Of course there's no 'valid' result from this sort. C could be anywhere such that it satisfies being smaller or larger than one of the adjacent elements. I'm thinking for a semi-efficient bubblesort that ignores the top element on the nth pass, for example, it might fail even that requirement. – Mike B Aug 09 '17 at 22:44
  • @Slava I know it's a bit of a longshot. I've done some extensive googling and I've found a couple people saying that they know std::sort will crash when you use a non-transitive comparator, but I guess I'm hoping somebody would be familiar with a specific usecase and would have faced it before, and be able to give me an idea for why this happens. In the live code that causes this issue, the problem is intermittant and I have no capacity to reproduce. Furthermore, the binary has had the debug symbols stripped so I struggle to follow the exact code path. – Mike B Aug 09 '17 at 22:47
  • So it appears (to me at least) that you're breaking the contract with the sort function and wondering why things are going wrong. It's this contract that allows the sort function to make assumptions when doing its job, assumptions that probably make it faster. Surely it would make more sense to either respect the contract or find a *different* sort function that allows for your case. I too am curious that, if you have a sorted list `a, b` and you want to insert a `c` that's both less than `a` and more than `b` (and also possibly *between* `a` and `b`), where is it meant to go? – paxdiablo Jun 18 '20 at 04:20
  • Does this answer your question? [Bewildering SegFault involving STL sort algorithm](https://stackoverflow.com/questions/2441045/bewildering-segfault-involving-stl-sort-algorithm) – yugr Jan 23 '21 at 21:22

0 Answers0