Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transposing a view throws an expection #651

Closed
schra opened this issue Feb 19, 2018 · 7 comments · Fixed by #652
Closed

Transposing a view throws an expection #651

schra opened this issue Feb 19, 2018 · 7 comments · Fixed by #652

Comments

@schra
Copy link

schra commented Feb 19, 2018

This code

xt::xarray<int> vector = xt::linspace(1, 10, 10);
auto matrix = xt::view(vector, xt::all(), xt::newaxis());

std::cout << xt::transpose(matrix) << std::endl;

throws an expection:

terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Aborted (core dumped)

The expected behavior is to print the following:

{{ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10}}

I'm using the master branch of xtensor (0872366).

Just to be clear: The intend of my C++ code is to express this NumPy code:

linspace(1, 10, 10)[:, newaxis].T

Output of GDB:

(gdb) bt
#0  __cxxabiv1::__cxa_throw (obj=0x55555578a4e0, tinfo=0x7ffff7279dd0 <typeinfo for std::bad_alloc>, dest=0x7ffff6f8bb60 <std::bad_alloc::~bad_alloc()>) at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_throw.cc:75
#1  0x00007ffff6fb8104 in std::__throw_bad_alloc () at /build/gcc/src/gcc/libstdc++-v3/src/c++11/functexcept.cc:54
#2  0x0000555555558b77 in __gnu_cxx::new_allocator<unsigned long>::allocate (this=0x7fffffffe2b0, __n=18446744073709551545) at /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../include/c++/7.2.1/ext/new_allocator.h:102
#3  0x0000555555558a23 in xt::svector<unsigned long, 4ul, std::allocator<unsigned long>, true>::grow (this=0x7fffffffe2b0, min_capacity=18446744073709551545) at xtensor/include/xtensor/xstorage.hpp:1102
#4  0x0000555555559bcd in xt::svector<unsigned long, 4ul, std::allocator<unsigned long>, true>::resize (this=0x7fffffffe2b0, n=18446744073709551545) at xtensor/include/xtensor/xstorage.hpp:814
#5  0x000055555555a8f7 in xt::svector<unsigned long, 4ul, std::allocator<unsigned long>, true>::swap<4ul, std::allocator<unsigned long>, true> (this=0x7fffffffe2b0, rhs=...) at xtensor/include/xtensor/xstorage.hpp:1057
#6  0x000055555555a6a1 in xt::svector<unsigned long, 4ul, std::allocator<unsigned long>, true>::svector (this=0x7fffffffe2b0, rhs=...) at xtensor/include/xtensor/xstorage.hpp:751
#7  0x000055555555990f in xt::xstrided_view<xt::xview<xt::xarray_container<xt::uvector<int, std::allocator<int> >, (xt::layout_type)1, xt::svector<unsigned long, 4ul, std::allocator<unsigned long>, true>, xt::xtensor_expression_tag>&, xt::xall<unsigned long>, xt::xnewaxis<unsigned long> >&, xt::svector<unsigned long, 4ul, std::allocator<unsigned long>, true>, xt::uvector<int, std::allocator<int> > const&>::xstrided_view (this=0x7fffffffe2a0, e=..., shape=..., 
    strides=..., offset=0, layout=xt::layout_type::dynamic) at xtensor/include/xtensor/xstrided_view.hpp:253
#8  0x00005555555572ae in xt::transpose<xt::xview<xt::xarray_container<xt::uvector<int, std::allocator<int> >, (xt::layout_type)1, xt::svector<unsigned long, 4ul, std::allocator<unsigned long>, true>, xt::xtensor_expression_tag>&, xt::xall<unsigned long>, xt::xnewaxis<unsigned long> >&> (e=...) at xtensor/include/xtensor/xstrided_view.hpp:762
#9  0x0000555555556b74 in main () at test.cpp:50
@wolfv
Copy link
Member

wolfv commented Feb 19, 2018

Ok, for some reason we try to allocate a shape with extremely large size in this line #2 (__n=18446744073709551545)...

Looks like subtracting something from a std::size_t.
I'll look into it.

@SylvainCorlay
Copy link
Member

On cling, everything seems to be ok until std::cout << xt::transpose(matrix) << std::endl;, assigning xt::transpose(matrix) to an xarray equally fails.

@wolfv
Copy link
Member

wolfv commented Feb 19, 2018

I just tested move assign and swap of svector and it seems to work. Will step through it with GDB.

@wolfv
Copy link
Member

wolfv commented Feb 19, 2018

Ok, the problem is definitly in this line, investigating:

std::copy(e.shape().rbegin(), e.shape().rend(), shape.begin());

@wolfv
Copy link
Member

wolfv commented Feb 19, 2018

Nope, wrong, I think now that the problem is that we're not initializing a stride of 0 for xt::newaxis.

@wolfv
Copy link
Member

wolfv commented Feb 19, 2018

Ah, well ... I got it now. the problem is that we're returning a computed temporary strides container from xt::view. And since we're calling expr.strides().begin(), and expr.strides().end() on two different temporaries, the iterator bounds are invalid.

We could take strides as a copy, but that doesn't sound like a great solution. Or we could somehow cache the strides in the xview which sounds like a slightly better solution.
Thoughts? @SylvainCorlay @JohanMabille

@JohanMabille
Copy link
Member

@wolfv I would go for caching the strides in the view, and computes them the first time we need them (as we do for the shape of xfunction_base.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants