yixuan / spectra

A header-only C++ library for large scale eigenvalue problems
https://spectralib.org
Mozilla Public License 2.0
745 stars 131 forks source link

-Wuse-after-free with gcc 12.1.0 #141

Closed jschueller closed 1 year ago

jschueller commented 2 years ago

with gcc 12.1.0 and CMAKE_CXX_FLAGS="-Wall -DNDEBUG" spectra issues a -Wuse-after-free warning:

[ 75%] Building CXX object test/CMakeFiles/GenEigs.dir/GenEigs.cpp.o
In file included from /usr/include/eigen3/Eigen/Core:166,
                 from /home/schueller/projects/spectra/test/GenEigs.cpp:1:
In function 'void Eigen::internal::aligned_free(void*)',
    inlined from 'void Eigen::internal::conditional_aligned_free(void*) [with bool Align = true]' at /usr/include/eigen3/Eigen/src/Core/util/Memory.h:259:15,
    inlined from 'void Eigen::internal::conditional_aligned_delete_auto(T*, std::size_t) [with T = double; bool Align = true]' at /usr/include/eigen3/Eigen/src/Core/util/Memory.h:446:34,
    inlined from 'Eigen::DenseStorage<T, -1, -1, _Cols, _Options>::~DenseStorage() [with T = double; int _Cols = 1; int _Options = 0]' at /usr/include/eigen3/Eigen/src/Core/DenseStorage.h:621:109,
    inlined from 'Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1> >::~PlainObjectBase()' at /usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:98:7,
    inlined from 'Eigen::Matrix<double, -1, 1>::~Matrix()' at /usr/include/eigen3/Eigen/src/Core/Matrix.h:178:7,
    inlined from 'void Spectra::UpperHessenbergEigen<Scalar>::doComputeEigenvectors() [with Scalar = double]' at /home/schueller/projects/spectra/include/Spectra/LinAlg/UpperHessenbergEigen.h:39:5:
/usr/include/eigen3/Eigen/src/Core/util/Memory.h:203:9: warning: pointer may be used after 'void free(void*)' [-Wuse-after-free]
  203 |     free(ptr);
      |     ~~~~^~~~~
In function 'void Eigen::internal::aligned_free(void*)',
    inlined from 'void Eigen::internal::conditional_aligned_free(void*) [with bool Align = true]' at /usr/include/eigen3/Eigen/src/Core/util/Memory.h:259:15,
    inlined from 'void Eigen::internal::conditional_aligned_delete_auto(T*, std::size_t) [with T = double; bool Align = true]' at /usr/include/eigen3/Eigen/src/Core/util/Memory.h:446:34,
    inlined from 'void Eigen::DenseStorage<T, -1, -1, _Cols, _Options>::resize(Eigen::Index, Eigen::Index, Eigen::Index) [with T = double; int _Cols = 1; int _Options = 0]' at /usr/include/eigen3/Eigen/src/Core/DenseStorage.h:637:77,
    inlined from 'void Eigen::PlainObjectBase<Derived>::resize(Eigen::Index, Eigen::Index) [with Derived = Eigen::Matrix<double, -1, 1>]' at /usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:285:25,
    inlined from 'static void Eigen::internal::Assignment<DstXprType, Eigen::Product<Lhs, Rhs, Options>, Eigen::internal::assign_op<Scalar, Scalar>, Eigen::internal::Dense2Dense, typename Eigen::internal::enable_if<((Options == Eigen::DefaultProduct) || (Options == Eigen::AliasFreeProduct))>::type>::run(DstXprType&, const SrcXprType&, const Eigen::internal::assign_op<Scalar, Scalar>&) [with DstXprType = Eigen::Matrix<double, -1, 1>; Lhs = Eigen::Block<Eigen::Matrix<double, -1, -1>, -1, -1, true>; Rhs = Eigen::Block<Eigen::Block<Eigen::Matrix<double, -1, -1>, -1, 1, true>, -1, 1, false>; int Options = 0; Scalar = double]' at /usr/include/eigen3/Eigen/src/Core/ProductEvaluators.h:146:17,
    inlined from 'void Eigen::internal::call_assignment_no_alias(Dst&, const Src&, const Func&) [with Dst = Eigen::Matrix<double, -1, 1>; Src = Eigen::Product<Eigen::Block<Eigen::Matrix<double, -1, -1>, -1, -1, true>, Eigen::Block<Eigen::Block<Eigen::Matrix<double, -1, -1>, -1, 1, true>, -1, 1, false>, 0>; Func = assign_op<double, double>]' at /usr/include/eigen3/Eigen/src/Core/AssignEvaluator.h:890:49,
    inlined from 'ExpressionType& Eigen::NoAlias<ExpressionType, StorageBase>::operator=(const StorageBase<OtherDerived>&) [with OtherDerived = Eigen::Product<Eigen::Block<Eigen::Matrix<double, -1, -1>, -1, -1, true>, Eigen::Block<Eigen::Block<Eigen::Matrix<double, -1, -1>, -1, 1, true>, -1, 1, false>, 0>; ExpressionType = Eigen::Matrix<double, -1, 1>; StorageBase = Eigen::MatrixBase]' at /usr/include/eigen3/Eigen/src/Core/NoAlias.h:43:31,
    inlined from 'void Spectra::UpperHessenbergEigen<Scalar>::doComputeEigenvectors() [with Scalar = double]' at /home/schueller/projects/spectra/include/Spectra/LinAlg/UpperHessenbergEigen.h:36:29:
/usr/include/eigen3/Eigen/src/Core/util/Memory.h:203:9: note: call to 'void free(void*)' here
  203 |     free(ptr);
      |     ~~~~^~~~~
[100%] Linking CXX executable GenEigs

here is a minimal example to reproduce:

#include <Spectra/GenEigsSolver.h>

class KLMatProd
{
public:
  using Scalar = double;

  KLMatProd()
  {
  }

  virtual ~KLMatProd() {}

  virtual int rows() const
  {
    return 0;
  }

  virtual int cols() const
  {
    return 0;
  }

  virtual void perform_op(const Scalar * x_in, Scalar * y_out) const
  {
    (void)x_in;
    (void)y_out;
  }
};

int main()
{
  KLMatProd op;
  Spectra::GenEigsSolver<KLMatProd> solver(op, 8,3);
  solver.init();
  solver.compute(Spectra::SortRule::LargestMagn);
  return 0;
}

in UpperHessenbergEigen::doComputeEigenvectors, if I remove the ".noalias()" below the warning goes away:

       // Back transformation to get eigenvectors of original matrix
        Vector m_tmp(size);
        for (Index j = size - 1; j >= 0; j--)
        {
            m_tmp.noalias() = m_eivec.leftCols(j + 1) * m_matT.col(j).segment(0, j + 1);
            m_eivec.col(j) = m_tmp;
        }

I dont know if it"s an actual spectra issue though

jschueller commented 1 year ago

looks like a gcc 12 only issue (ok with gcc 13)