I have the following issue when compiling in release mode
using MSVC 19.31.31106.2 (and C++17, as far as I understand the eigen page, alignment should be not an issue anymore) that I get a segfault from within of std::sort.
The official Eigen 3.4 release is used.
The following compiler flags are set:
/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"
So I have the following struct:
struct MyStruct
{
Eigen::Matrix<double, 2, 1> mVecA{};
Eigen::Matrix<double, 2, 1> mVecB{};
bool mA = true;
uint64_t mB = 0;
};
Then after filling a vector std::vector<MyStruct> myVec; with some data the call to
std::sort(myVec.begin(), myVec.end(), [](const MyStruct& lhs, const MyStruct& rhs) { return lhs.mB < rhs.mB; });
causes a segfault (whereas using std::stable_sort causes no issue) it seems to be thrown from inside of std::move. In debug mode this does not happen.
Further when changing the order of MyStruct to
struct MyStruct
{
bool mA = true;
uint64_t mB = 0;
Eigen::Matrix<double, 2, 1> mVecA{};
Eigen::Matrix<double, 2, 1> mVecB{};
};
the segfault does not appear anymore at all. I don't really understand why this order would be an issue? Shouldn't it also be preferable to avoid unecessary padding within the struct?
Another thing that could fix it would be to explicitly defie alignment for the eigen matrices:
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;
};
Here is a minimal example (AVX2 is enabled in the CMake and Eigen needs to be included): Here is an godbolt example: https://godbolt.org/z/odned4axW. (It only works when /MD is not added to the flags, otherwise it will not run at all.. which is different from the behaviour on my local machine, where it can still run with /MD but causes an exception in the move constructor)
#include <Eigen/Core>
#include <Eigen/Dense>
#include <Eigen/StdVector>
#include <stdint.h>
#include <algorithm>
#include <stdlib.h>
#include <iostream>
int main()
{
struct MyStruct
{
MyStruct() = default;
MyStruct(const Eigen::Matrix<double, 2, 1>& vecA, const Eigen::Matrix<double, 2, 1>& vecB, uint64_t value, bool boo) : mVecA(vecA), mVecB(vecB), mValue(value), mBool(boo) {}
alignas(32) Eigen::Matrix<double, 2, 1> mVecA{};
alignas(32) Eigen::Matrix<double, 2, 1> mVecB{};
uint64_t mValue = 0;
bool mBool = true;
};
std::vector<MyStruct> mSorted;
for (uint64_t i = 0; i < 1000; i++)
mSorted.emplace_back(Eigen::Matrix<double, 2, 1>::Random(), Eigen::Matrix<double, 2, 1>::Random(), static_cast<uint64_t>(rand()), true);
std::sort(mSorted.begin(), mSorted.end(), [](const MyStruct& lhs, const MyStruct& rhs) { return lhs.mValue < rhs.mValue; });
std::cout << mSorted[0].mValue << std::endl;
std::cout << "Super test" << std::endl;
}
The error occurs in PlainObjectBase.h line 496 (move constructor of PlainObjectBase) traced from (std::sort -> std::_Sort_unchecked -> std::_Partition_by_median_guess_unchecked -> std::iter_swap -> std::swap).