|
Boost : |
Subject: Re: [boost] [gil] gcc fail with simple code
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2018-03-28 18:01:57
On 03/28/18 20:52, Andrey Semashev wrote:
> On 03/28/18 20:30, Christian Henning via Boost wrote:
>> Hi all,
>>
>> we are, at the boost::gil corner, investigating a runtime failure when
>> compiling with gcc 5.4. When running in release configuration the
>> following
>> code fails:
>>
>> #include <iostream>
>> #include <boost/gil/gil_all.hpp>
>>
>> using namespace boost::gil;
>> using namespace std;
>>
>> void error_if(bool condition) {
>> Â Â Â Â if (condition)
>> Â Â Â Â Â Â Â Â throw std::exception();
>> }
>>
>> bits32s c32s_min = channel_traits<bits32s>::min_value();
>> bits32s c32s_max = channel_traits<bits32s>::max_value();
>>
>> // For channel values simply initialize the value directly
>> template <typename ChannelValue>
>> struct value_core {
>> Â Â Â Â typedef ChannelValue channel_t;
>> Â Â Â Â channel_t _min_v, _max_v;
>>
>> Â Â Â Â value_core() : _min_v(channel_traits<ChannelValue>::min_value()),
>> _max_v(channel_traits<ChannelValue>::max_value())
>> Â Â Â Â {}
>> };
>>
>> int main(int argc, char *argv[])
>> {
>> Â Â Â Â value_core<bits32s> a;
>>
>> Â Â Â Â bits32s v_min, v_max;
>>
>> Â Â Â Â v_min = channel_convert<bits32s>(c32s_min);
>> Â Â Â Â v_max = channel_convert<bits32s>(c32s_max);
>>
>> Â Â Â Â //std::cout << v_min << std::endl;
>> Â Â Â Â // std::cout << this->_min_v << std::endl;
>> Â Â Â Â //std::cout << v_max << std::endl;
>> Â Â Â Â // std::cout << this->_max_v << std::endl;
>>
>> Â Â Â Â error_if(v_min != a._min_v || v_max != a._max_v);
>> }
>>
>> The interesting thing is that everything works with the cout's enabled.
>>
>> Has anyone ever dealt with a similar issue?
>
> Most likely, you have a signed integer overflow somewhere. The code
> crashes on gcc 7.2 with -O3 but doesn't crash with -O0 or with -O3 -fwrapv.
With -ftrapv the code crashes at this point:
#0 __GI_raise (sig=sig_at_entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00007ffff7490f5d in __GI_abort () at abort.c:90
#2 0x00007ffff783b2d8 in __addvsi3 () from
/lib/x86_64-linux-gnu/libgcc_s.so.1
#3 0x00005555555548a9 in
boost::gil::detail::channel_convert_to_unsigned<int>::operator()
(this=<optimized out>, x=<optimized out>) at
./boost/gil/channel_algorithm.hpp:332
#4 boost::gil::channel_converter<int, int>::operator() (this=<optimized
out>, src=@0x555555755014: 2147483647) at
./boost/gil/channel_algorithm.hpp:368
#5 boost::gil::channel_convert<int, int> (src=@0x555555755014:
2147483647) at ./boost/gil/channel_algorithm.hpp:377
#6 main (argc=<optimized out>, argv=<optimized out>) at test_gil.cpp:32
channel_algorithm.hpp:332 is this line:
type operator()(bits32s x) const { return
static_cast<bits32>(x+(1<<31)); }
This shift is UB because it overflows (until C++17, I think?). The
addition will also overflow unless x is 0.
I would suggest casting to unsigned first and then performing the math.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk