std::sort 与包含 Eigen 数据类型的结构会导致段错误

Ani*_*ima 9 c++ eigen eigen3

MSVC 19.31.31106.2在使用(和 C++17,据我了解特征页,对齐应该不再是问题)在发布模式下编译时,我遇到了以下问题,我segfaultstd::sort. 使用的是官方发布的Eigen 3.4版本。

设置了以下编译器标志:

/errorReport:prompt /WX /Zc:forScope /GR /arch:AVX2 /Gd /MD /std:c++17 /GS /W4 /wd"4389" /wd"4996" /wd"4244" /wd"4324" /wd"4127" /Zc:wchar_t  /EHsc /nologo /Gm- /O2 /Ob2 /Zc:inline /fp:precise /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "NDEBUG" /D "_CRT_SECURE_NO_WARNINGS"  
Run Code Online (Sandbox Code Playgroud)

所以我有以下结构:

/errorReport:prompt /WX /Zc:forScope /GR /arch:AVX2 /Gd /MD /std:c++17 /GS /W4 /wd"4389" /wd"4996" /wd"4244" /wd"4324" /wd"4127" /Zc:wchar_t  /EHsc /nologo /Gm- /O2 /Ob2 /Zc:inline /fp:precise /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "NDEBUG" /D "_CRT_SECURE_NO_WARNINGS"  
Run Code Online (Sandbox Code Playgroud)

然后在用一些数据填充向量后std::vector<MyStruct> myVec;调用

struct MyStruct
{
    Eigen::Matrix<double, 2, 1> mVecA{}; 
    Eigen::Matrix<double, 2, 1> mVecB{};  
    bool mA = true;
    uint64_t mB = 0;
};
Run Code Online (Sandbox Code Playgroud)

导致段错误(而使用std::stable_sort不会导致问题),它似乎是从std::move. 在调试模式下,这种情况不会发生。MyStruct此外,当改变顺序时

std::sort(myVec.begin(), myVec.end(), [](const MyStruct& lhs, const MyStruct& rhs) { return lhs.mB < rhs.mB; });
Run Code Online (Sandbox Code Playgroud)

段错误根本不再出现。我真的不明白为什么这个订单会成为一个问题?难道不应该更好地避免结构中不必要的填充吗?

可以解决这个问题的另一件事是明确地拒绝特征矩阵的对齐:

struct MyStruct
{
    bool mA = true;
    uint64_t mB = 0;
    Eigen::Matrix<double, 2, 1> mVecA{}; 
    Eigen::Matrix<double, 2, 1> mVecB{};  
};
Run Code Online (Sandbox Code Playgroud)

这是一个最小的示例(AVX2 在 CMake 中启用,并且需要包含 Eigen):这是一个 godbolt 示例: https: //godbolt.org/z/odned4axW。(它仅在未添加到标志时才有效/MD,否则它根本不会运行..这与我本地计算机上的行为不同,它仍然可以运行,/MD但会在构造函数中导致异常move

struct MyStruct
{
    alignas(32) Eigen::Matrix<double, 2, 1> mVecA{}; 
    alignas(32) Eigen::Matrix<double, 2, 1> mVecB{};  
    bool mA = true;
    uint64_t mB = 0;
};
Run Code Online (Sandbox Code Playgroud)

该错误发生在从 ( -> -> -> -> )追踪的PlainObjectBase.h第 496 行( 的移动构造函数) 。PlainObjectBasestd::sortstd::_Sort_uncheckedstd::_Partition_by_median_guess_uncheckedstd::iter_swapstd::swap