[Bug libstdc++/83860] [6/7/8 Regression] valarray replacement type breaks with auto and more than one operation

redi at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Tue Mar 27 16:09:00 GMT 2018


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83860

--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Richard Biener from comment #1)
> Confirmed.  Works with GCC 5

Well, it doesn't segfault, but ASan still shows the problem:



ASAN:SIGSEGV
=================================================================
==8343==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000018 (pc
0x0000004017e9 bp 0x7ffc01d53a90 sp 0x7ffc01d53a80 T0)
    #0 0x4017e8 in std::valarray<int>::operator[](unsigned long) const
/home/jwakely/gcc/5.5.0/include/c++/5.5.0/valarray:571
    #1 0x401792 in std::_BinBase<std::__plus, std::valarray<int>,
std::valarray<int> >::operator[](unsigned long) const
/home/jwakely/gcc/5.5.0/include/c++/5.5.0/bits/valarray_before.h:534
    #2 0x4016b5 in std::_BinBase<std::__plus, std::_BinClos<std::__plus,
std::_ValArray, std::_ValArray, int, int>, std::valarray<int>
>::operator[](unsigned long) const
/home/jwakely/gcc/5.5.0/include/c++/5.5.0/bits/valarray_before.h:534
    #3 0x4015ea in std::_Expr<std::_BinClos<std::__plus, std::_Expr,
std::_ValArray, std::_BinClos<std::__plus, std::_ValArray, std::_ValArray, int,
int>, int>, int>::operator[](unsigned long) const
/home/jwakely/gcc/5.5.0/include/c++/5.5.0/bits/valarray_after.h:216
    #4 0x4013fd in void std::__valarray_copy_construct<int,
std::_BinClos<std::__plus, std::_Expr, std::_ValArray,
std::_BinClos<std::__plus, std::_ValArray, std::_ValArray, int, int>, int>
>(std::_Expr<std::_BinClos<std::__plus, std::_Expr, std::_ValArray,
std::_BinClos<std::__plus, std::_ValArray, std::_ValArray, int, int>, int>,
int> const&, unsigned long, std::_Array<int>)
/home/jwakely/gcc/5.5.0/include/c++/5.5.0/bits/valarray_array.tcc:219
    #5 0x4011a9 in std::valarray<int>::valarray<std::_BinClos<std::__plus,
std::_Expr, std::_ValArray, std::_BinClos<std::__plus, std::_ValArray,
std::_ValArray, int, int>, int> >(std::_Expr<std::_BinClos<std::__plus,
std::_Expr, std::_ValArray, std::_BinClos<std::__plus, std::_ValArray,
std::_ValArray, int, int>, int>, int> const&)
/home/jwakely/gcc/5.5.0/include/c++/5.5.0/valarray:696
    #6 0x400d1c in main /tmp/val.cc:6
    #7 0x7f025472a889 in __libc_start_main (/lib64/libc.so.6+0x20889)
    #8 0x400ae9 in _start (/tmp/val5+0x400ae9)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV
/home/jwakely/gcc/5.5.0/include/c++/5.5.0/valarray:571
std::valarray<int>::operator[](unsigned long) const
==8343==ABORTING


The root cause is that binary operators for valarray return expression
templates that have reference semantics, not value semantics. The result of
va+vb+vc refers to a temporary object that goes out of scope at the end of the
full expression. When that result is stored in a valarray it works OK:

  std::valarray<int> sum = va + vb + vc;

but when you use 'auto' you get an object of the expression template type,
which holds a dangling reference to an expired temporary.

Solution: Don't use 'auto' with expression templates.

I'll see if there's anything the library can do to make this less error-prone.


More information about the Gcc-bugs mailing list