Boost logo

Ublas :

From: Paul C. Leopardi (leopardi_at_[hidden])
Date: 2005-11-12 19:21:08


Hi all,
When compiling GluCat with uBLAS CVS using g++ 4.0.2, I get warning messages
of the following kind.

if /usr/local/gcc/gcc-4.0.2/bin/g++ -DHAVE_CONFIG_H -I. -I. -I..
-Wstrict-aliasing=2 -Wall -ansi -DNDEBUG -g -O1 -finline-limit=400
-fno-check-new -fabi-version=0 -fexceptions -MT transforms.o -MD -MP -MF
".deps/transforms.Tpo" -c -o transforms.o transforms.cpp; \
then mv -f ".deps/transforms.Tpo" ".deps/transforms.Po"; else rm -f
".deps/transforms.Tpo"; exit 1; fi
../boost/numeric/ublas/operation_sparse.hpp: In function ‘M&
boost::numeric::ublas::sparse_prod(const
boost::numeric::ublas::matrix_expression<RHS_T>&, const
boost::numeric::ublas::matrix_expression<E2>&, M&, TRI,
boost::numeric::ublas::row_major_tag) [with M =
boost::numeric::ublas::compressed_matrix<double,
boost::numeric::ublas::basic_row_major<size_t, ptrdiff_t>, 0ul,
boost::numeric::ublas::unbounded_array<size_t, std::allocator<size_t> >,
boost::numeric::ublas::unbounded_array<double, std::allocator<double> > >, E1
= boost::numeric::ublas::compressed_matrix<double,
boost::numeric::ublas::basic_row_major<size_t, ptrdiff_t>, 0ul,
boost::numeric::ublas::unbounded_array<size_t, std::allocator<size_t> >,
boost::numeric::ublas::unbounded_array<double, std::allocator<double> > >, E2
= boost::numeric::ublas::compressed_matrix<double,
boost::numeric::ublas::basic_row_major<size_t, ptrdiff_t>, 0ul,
boost::numeric::ublas::unbounded_array<size_t, std::allocator<size_t> >,
boost::numeric::ublas::unbounded_array<double, std::allocator<double> > >,
TRI = boost::numeric::ublas::basic_full<size_t>]’:
../boost/numeric/ublas/operation_sparse.hpp:42: warning:
‘temporary$data_$data_’ may be used uninitialized in this function

The warning message should say

'temporary.data_.data_' may be used uninitialized in this function

See GCC bug 14329: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14329

Also, the warning message does not indicate where temporary.data_.data_ should
have been initialized, nor where it could be used uninitialized. We need to
drill down to do this. I have done so and it looks like the warning is
spurious. See details below.

There are a number of GCC bugs which mention similar spurious warnings. See
for example GCC bugs 20968, 21548 and 21733.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20968
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21548
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21733

Even though the warning is probably spurious, I have locally fixed storage.hpp
to eliminate the warning, and have attached a diff file to this message. The
fix is simply to always initialize data_ to 0 before entering the body of a
constructor for unbounded_array.

Should this fix be applied to uBLAS CVS?
Best regards, Paul Leopardi

Details of drill down.

Line 42 of ublas/operation_sparse.hpp says

vector<value_type> temporary (e2 ().size2 ());

The warning actually refers to the constructor for
vector<value_type>(size_type size), which via ublas/fwd.hpp defaults to the
constructor for
vector<value_type, unbounded_array<value_type> >(size_type size)
which is defined at lines 57 to 60 of vector.hpp.

Line 59 calls the constructor for _data(size), ie. the constructor for
unbounded_array<value_type>(size_type size), which via ublas/fwd.hpp
defaults to the constructor for
unbounded_array<value_type, std::allocator<value_type> >(size_type size),
which is defined on lines 62 to 80 of ublas/storage.hpp:

        explicit BOOST_UBLAS_INLINE
        unbounded_array (size_type size, const ALLOC &a = ALLOC()):
            alloc_(a), size_ (size) {
            if (size_) {
                data_ = alloc_.allocate (size_);
                // ISSUE some compilers may zero POD here
#ifdef BOOST_UBLAS_USEFUL_ARRAY_PLACEMENT_NEW
                // array form fails on some compilers due to size cookie, is
>>>> it standard conforming?
                new (data_) value_type[size_];
#else
                for (pointer d = data_; d != data_ + size_; ++d)
                    new (d) value_type;
#endif
            }
#ifndef NDEBUG
            else
                data_ = 0; // simplify debugging by giving data_ a definate
>>>> value
#endif
        }

We see that if NDEBUG is defined, then if size is zero, then data_ is not
initialized.

On line 43 of ublas/operation_sparse.hpp we have

        temporary.clear ();

This calls vector<value_type>.clear() with temporary as *this. The clear()
function is defined on lines 152 to 155 of ublas/vector.hpp:

        BOOST_UBLAS_INLINE
        void clear () {
            std::fill (data ().begin (), data ().end (),
>>>> value_type/*zero*/());
        }

The clear() function uses data(), defined on lines 94 to 97 of
ublas/vector.hpp:

        BOOST_UBLAS_INLINE
        const array_type &data () const {
            return data_;
        }

Note this is temporary.data_, not temporary.data_.data_
If we drill down on data ().begin () and data ().end () we see that if size is
zero, then they both return the same value. Lines 377 to 384 of
ublas/vector.hpp:

        BOOST_UBLAS_INLINE
        const_iterator begin () const {
            return find (0);
        }
        BOOST_UBLAS_INLINE
        const_iterator end () const {
            return find (data_.size ());
        }