从gcc / g ++ 8.1 更新到 9.1 并重新编译我的代码后,其大多数测试均失败了。因此,进行了一些挖掘,发现std::stable_sort
是问题所在。
事实证明,我对std::stable_sort
的呼叫中的大多数呼叫都是不必要的,也就是说,呼叫std::sort
就足够了。因此,我在可能的地方进行了替换,有关这些代码段的测试再次成功。
现在,我只有一个电话打到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
}
其中 conns 是std::vector<std::vector<int>>
,用于存储元素的连通性。排序是基于列 index 进行的,其值在类标题中分配,并且 conns 中的所有std::vector<int>
都有该条目。
另一个值得一提的事实是,在 debug 构建中(使用了编译器标志“ -g”,没有使用“ -O3”),所有测试都成功。>
此外,通过在调用之前和之后打印 conns 的值,在 release 版本(使用标志“ -O3”,不使用“ -g”的情况下)上到std::stable_sort
,我发现 conns 毁了。
之前
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
之后
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
在调试版本中,std::stable_sort
输出预期结果。除此之外,还使用c++17
(编译器标志“ -std = c ++ 17”)。
因此
我打给std::stable_sort
的电话有问题吗?
g ++的哪些更改导致了此行为?
为什么这种行为仅出现在版本版本中?
最小示例
#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;
}
如果以上内容是用
编译的 g++ -o main main.cpp -m64 -std=c++17 -O3
它输出segmentation fault (core dumped)
。但是,如果不使用标志“ -O3”,则可以获得预期的结果。
答案 0 :(得分:2)
使用g ++ 9.1.1编译时,传递给lambda的第一个“ b
”具有size()==0
,这应该是不可能的。 clang ++ 8.0.0使用相同的编译标志可以毫无问题地运行它,并且在运行valgrind
时不会显示任何奇怪的东西。
我会说这是g ++中的错误。 lambda函数中带有调试输出的代码:
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <vector>
template<typename InputIt>
void print2D(InputIt cbegin, InputIt cend, const std::string&& message) {
std::cout << message;
for(auto i = cbegin; i != cend; ++i) {
for(auto j : *i) {
std::cout << "\t" << std::setw(3) << std::right << j;
}
std::cout << "\n";
}
std::cout << "\n";
}
int main() {
size_t 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) {
std::cout << index << "\ta.size=" << a.size() << " b.size=" << b.size() << "\n";
return a[index] < b[index];
});
print2D(conns.cbegin(), conns.cend(), "\n\n\tafter\n");
}
输出:
before
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
1 a.size=4 b.size=0
Segmentation fault (core dumped)