Comparing method issue when using STL sort
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;
}
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.
Your comparison function must return false
when the inputs are equal, not true
.
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
.
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.
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);
}
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.
精彩评论