After updating from gcc/g++ 8.1 to 9.1 and recompiling my code, most of its tests failed. Hence, a little digging was made and I have found out that std::stable_sort was the problem.
As it turns out, most calls of my calls to std::stable_sort were not necessary, that is, calling std::sort would be enough. Thus, I have done the substitution where it was possible, and the tests regarding these pieces of code succeed again.
Now, I have only one call to std::stable_sort
void MshReader::determinePhysicalEntitiesRange() {
// conns is not empty
std::stable_sort(this->conns.begin(), this->conns.end(),
[=](const auto& a, const auto& b){
return a[this->index] < b[this->index];
}
);
// acess some values of conns
}
Where conns is a std::vector<std::vector<int>> that stores element connectivities. The sorting is done based on column index, its value is assigned in the class header, and all std::vector<int> in conns have that entry.
Another fact worth mentioning is that, on debug builds (compiler flag "-g" is used, "-O3" is NOT) all tests succeed.
Also, on release builds (flag "-O3" is used, "-g" is NOT), by printing the values of conns before and after the call to std::stable_sort, I have discovered that conns is ruined.
Before
row:
0: 0 2 0 1
1: 0 2 1 2
2: 0 1 2 5
3: 0 1 5 8
4: 0 3 8 7
5: 0 3 7 6
6: 0 0 6 3
7: 0 0 3 0
8: 1 4 3 4 9
9: 1 4 3 9 6
10: 1 4 4 7 9
11: 1 4 6 9 7
12: 1 4 1 2 10
13: 1 4 1 10 4
14: 1 4 2 5 10
15: 1 4 4 10 5
16: 2 4 4 5 8 7
17: 2 4 0 1 4 3
After
row:
0: 0 0 6 3
1: 0 0 3 0
2: 0 1 2 5
3: 0 1 5 8
4: 0 2 1 2 // there were two rows with column 'index' = 2
5: 0 3 8 7
6: 0 3 7 6
7: 1 4 2 5 10 10 10 10 // this entry was previously on row 14; extra '10's
8: 1 4 3 4 9
9: 1 4 3 9 6
10: 1 4 4 7 9
11: 1 4 6 9 7
12: 1 4 1 2 10
13: 1 4 1 10 4
14: 1 4 2 5 10
15: 1 4 4 10 5
16: 2 4 4 5 8 7
17: 2 4 0 1 4 3
On debug builds, std::stable_sort outputs the expected result. Besides that, c++17 is being used (compiler flag "-std=c++17").
Therefore,
Is something wrong with my call to
std::stable_sort?Which changes on g++ led to this behavior?
Why this behavior only appears in release builds?
Minimal Example
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
template<typename InputIt>
void print2D(InputIt cbegin, InputIt cend, std::string&& message) {
std::cout << message;
for (auto i = cbegin; i != cend; ++i) {
for (auto j = i->cbegin(); j != i->cend(); ++j) {
std::cout << "\t" << std::setw(3) << std::right << *j;
}
std::cout << std::endl;
}
std::cout << std::endl;
}
int main() {
int index = 1;
std::vector<std::vector<int>> conns{{0,2,0,1},{0,2,1,2},{0,1,2,5},{0,1,5,8},{0,3,8,7},{0,3,7,6},{0,0,6,3},{0,0,3,0},{1,4,3,4,9},{1,4,3,9,6},{1,4,4,7,9},{1,4,6,9,7},{1,4,1,2,10},{1,4,1,10,4},{1,4,2,5,10},{1,4,4,10,5},{2,4,4,5,8,7},{2,4,0,1,4,3}};
print2D(conns.cbegin(), conns.cend(), "\n\n\tbefore\n");
std::stable_sort(conns.begin(), conns.end(),
[=](const auto& a, const auto& b){
return a[index] < b[index];
}
);
print2D(conns.cbegin(), conns.cend(), "\n\n\tafter\n");
return 0;
}
If the above is compiled with
g++ -o main main.cpp -m64 -std=c++17 -O3
It outputs segmentation fault (core dumped). However, if the flag "-O3" is not employed, the expected results is obtained.