-
Notifications
You must be signed in to change notification settings - Fork 421
Description
When using -DXTENSOR_FORCE_TEMPORARY_MEMORY_IN_ASSIGNMENTS=Off, the following simple test fails:
TEST(xbuilder, concatenate_assign_to_argument)
{
xt::xarray<int> a = xt::ones<int>({ 4 });
xt::xarray<int> b = xt::ones<int>({ 3 });
a = xt::concatenate(xt::xtuple(a, b));
ASSERT_EQ(a, xt::ones<int>({7}));
}
Instead of containing 7 ones, a
will contain garbage.
I have searched for the root cause of the issue, and found the following:
-
Changing
overlapping_memory_checker_traits
forxgenerator
, socheck_overlap
returnstrue
instead offalse
, solves the issue. The change is in line 90 of xgenerator.hpp. -
The problem occurs because of an assumption that an xgenerator always generates fresh values using some generator function. In this case, memory overlap indeed never occurs.
-
xt::concatenate
creates an xgenerator that reads values from the arrays in its input tuple, which may overlap with the output array.
The following happens in the test:
xgenerator::assign_to
resizesa
, so it can hold seven elements. It re-allocates memory for a, without initializing the elements.- The function in the xgenerator, which has type
concatenate_access
, still wants to concatenatea
andb
. It uses the new value fora
. - Since
a
now has length 7,concatenate_access::access
only uses values froma
. It thus copies the uninitialized values froma
toa
.
Although patching xgenerator works around the issue, a proper fix would be calling check_overlap
on the functor inside the xgenerator, and then calling check_overlap
on the tuples inside the functor, in case the functor holds a tuple.