mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Fix dangling reference in IndexedView with expression indices
libeigen/eigen!2335 Closes #1943
This commit is contained in:
committed by
Rasmus Munk Larsen
parent
624ab58e8d
commit
b7f6aed1b9
@@ -125,6 +125,15 @@ struct SymbolicExpressionEvaluator<FixedInt<N>, SizeAtCompileTime, void> {
|
||||
// Handling of generic indices (e.g. array)
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
// Detect Eigen expression types that are not plain objects (Matrix/Array).
|
||||
// These types may hold internal references to temporaries and must be evaluated before storing.
|
||||
template <typename T, typename = void>
|
||||
struct is_eigen_index_expression : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct is_eigen_index_expression<T, std::enable_if_t<!std::is_same<T, typename T::PlainObject>::value>>
|
||||
: std::true_type {};
|
||||
|
||||
// Potentially wrap indices in a type that is better-suited for IndexedView evaluation.
|
||||
template <typename Indices, int NestedSizeAtCompileTime, typename EnableIf = void>
|
||||
struct IndexedViewHelperIndicesWrapper {
|
||||
@@ -132,6 +141,15 @@ struct IndexedViewHelperIndicesWrapper {
|
||||
static const type& CreateIndexSequence(const Indices& indices, Index /*nested_size*/) { return indices; }
|
||||
};
|
||||
|
||||
// Specialization for Eigen expression types (Reshaped, Block, CwiseOp, etc.) used as indices.
|
||||
// These may hold dangling references to temporaries if not evaluated.
|
||||
template <typename Indices, int NestedSizeAtCompileTime>
|
||||
struct IndexedViewHelperIndicesWrapper<Indices, NestedSizeAtCompileTime,
|
||||
std::enable_if_t<is_eigen_index_expression<Indices>::value>> {
|
||||
using type = typename Indices::PlainObject;
|
||||
static type CreateIndexSequence(const Indices& indices, Index /*nested_size*/) { return indices.eval(); }
|
||||
};
|
||||
|
||||
// Extract compile-time and runtime first, size, increments.
|
||||
template <typename Indices, typename EnableIf = void>
|
||||
struct IndexedViewHelper {
|
||||
|
||||
@@ -840,6 +840,61 @@ void check_tutorial_examples() {
|
||||
}
|
||||
}
|
||||
|
||||
// Regression test for bug #1943: IndexedView with temporary expression indices.
|
||||
void check_expression_indices() {
|
||||
MatrixXd m(3, 4);
|
||||
m << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12;
|
||||
|
||||
// Reshaped temporary as column index (was segfault before fix).
|
||||
{
|
||||
auto view = m(all, Array<int, 1, 1>{0}.reshaped());
|
||||
VectorXd result = view;
|
||||
VERIFY_IS_APPROX(result, m.col(0));
|
||||
}
|
||||
|
||||
// Block expression as index.
|
||||
{
|
||||
ArrayXi idx(3);
|
||||
idx << 0, 1, 2;
|
||||
auto view = m(all, idx.head(2));
|
||||
MatrixXd result = view;
|
||||
VERIFY_IS_APPROX(result, m.leftCols(2));
|
||||
}
|
||||
|
||||
// CwiseBinaryOp expression as index.
|
||||
{
|
||||
Array<int, 2, 1> base;
|
||||
base << 0, 1;
|
||||
auto view = m(all, base + 0);
|
||||
MatrixXd result = view;
|
||||
VERIFY_IS_APPROX(result, m.leftCols(2));
|
||||
}
|
||||
|
||||
// Reverse expression as index.
|
||||
{
|
||||
Array<int, 3, 1> idx;
|
||||
idx << 2, 1, 0;
|
||||
auto view = m(all, idx.reverse());
|
||||
MatrixXd result = view;
|
||||
MatrixXd expected(3, 3);
|
||||
expected << m.col(0), m.col(1), m.col(2);
|
||||
VERIFY_IS_APPROX(result, expected);
|
||||
}
|
||||
|
||||
// 1D vector indexed view (VectorIndexedViewSelector path).
|
||||
{
|
||||
VectorXd v(5);
|
||||
v << 10, 20, 30, 40, 50;
|
||||
ArrayXi idx(3);
|
||||
idx << 4, 2, 0;
|
||||
auto view = v(idx.reverse());
|
||||
VectorXd result = view;
|
||||
VectorXd expected(3);
|
||||
expected << 10, 30, 50;
|
||||
VERIFY_IS_APPROX(result, expected);
|
||||
}
|
||||
}
|
||||
|
||||
void check_aliasing() {
|
||||
Eigen::Vector<float, 5> z = {0.0f, 1.1f, 2.2f, 3.3f, 4.4f};
|
||||
std::vector<int> left_indices = {0, 1, 3, 4};
|
||||
@@ -854,6 +909,7 @@ EIGEN_DECLARE_TEST(indexed_view) {
|
||||
CALL_SUBTEST_1(check_indexed_view());
|
||||
}
|
||||
CALL_SUBTEST_1(check_tutorial_examples());
|
||||
CALL_SUBTEST_1(check_expression_indices());
|
||||
CALL_SUBTEST_1(check_aliasing());
|
||||
|
||||
// static checks of some internals:
|
||||
|
||||
Reference in New Issue
Block a user