0

Consider the following code. It is supposed to sort vector of vectors of ints in lexicographical order, i.e. by first column at first and then by second and so on. In my application I only care about first 6 out of 8 columns so was returning true in the case when values are equal for the first 6 columns.

And it caused problems (segmentation fault). It was working for 1000 data and it crashed for 1001. The example code is toy but sorting is a part of quite complicated program. I found out after long debugging that it was the cause of troubles. The program tries to sort array of all zeros with one (1, 0, ..., 0) entry.

Please any expert in C++, can you tell me what is wrong with the original (listed) program?

I was compiling it on 32bit and 64bit Linux and Visual Studio on 32bit Windows. It was always crashing. After the change in comment everything seems fine.

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

const int COLS = 8;

bool compare (const vector<int>& r1, const vector<int>& r2)
{         
   for (int i = 0; i < COLS-2; i++)
     if ( r1[ i ] != r2[ i ] )
      return (r1[ i ] < r2[ i ]);
   return true; //if true is replace by r1[ COLS-1 ] < r2[ COLS-1 ] then is OK
};

int main(int argc, char **argv) 
{       
    int Na = 20;
    vector< vector<int> > v( Na );

    for (int r = 0; r < v.size(); r++)
      v[r].resize(COLS, 0);
    v[0][0] = 1;

    cout << "Sorting\n";
    sort( v.begin(), v.end(), compare );
    cout << "Eof Sorting\n";         

    return 0;
} 
4
  • The code comment already explains the problem. Sort needs a compare for less than, not for equality. Commented Mar 25, 2011 at 22:44
  • 1
    @Bo Persson: That won't cause a memory access violation, just an illogical result. Commented Mar 25, 2011 at 22:46
  • 1
    @DeadMG - It might if std::sort runs amok when it can't find a consistent ordering. Depends on the implementation though. Commented Mar 25, 2011 at 22:49
  • Does this mean that if I have weak inequality (<=) instead of < in comparing function then its wrong if I use sort? Commented Mar 25, 2011 at 23:38

6 Answers 6

4

I think you are blowing the stack. The sort function is implemented recursively, so if you give inconsistent answers about the order relationships among elements, the algorithm may fail to terminate.

Sign up to request clarification or add additional context in comments.

Comments

4

Your comparison function must return false when the inputs are equal, not true.

2 Comments

Thats right. But I am still thinking why i.e. don't fully understand it
@user677514, my bet is on Jollymorphic's answer.
2

The problem is your compare-function:

bool compare (const vector<int>& r1, const vector<int>& r2)
{         
   for (int i = 0; i < COLS-2; i++)
     if ( r1[ i ] != r2[ i ] )
      return (r1[ i ] < r2[ i ]);
   return true; //if true is replace by r1[ COLS-1 ] < r2[ COLS-1 ] then is OK
};

If the elements are equal the expression r1 < r2 is false - but in case of equality (in your case if first 6 ints are equal) you return true.

Comments

1

This is not necessarily related to the question (it would not contribute to a crash), but the code is skipping one column. The code compares 6 (8-2) columns and then (if using the uncommented code), it would compare the last column. The next-to-last is not examined. However, that might be the intent ... if so, though, a comment would probably be good if the code has to exist for any amount of time.

Comments

1

If you want to sort in lexicographical order you can use the standard library:

bool compare (const vector<int>& r1, const vector<int>& r2)
{  
   return std::lexicographical_compare(r1.begin(), r1.begin()+6, r2.begin(), r2.begin()+6);
}

Comments

0

I expect you are running off the end of one of your vectors, which will have undefined results in release builds.

On linux, run your program using the excellent Valgrind.

You can also make your code so it only examines actual slots in the vectors, such as:

bool compare (const vector<int>& r1, const vector<int>& r2)
{  
   const int max = std::min(r1.size(),r2.size());
   for (int i = 0; i<max; i++)
     if ( r1[ i ] != r2[ i ] )
      return (r1[ i ] < r2[ i ]);
   return r1.size() < r2.size();
};

However, if you are expecting an exact number of slots then that's a logic bug and making your compare function ignore it is not necessarily a good solution.

1 Comment

In the real program there is assertion that sizes are equal.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.