Opened 7 years ago

Closed 7 years ago

#11426 closed Bugs (wontfix)

Warning C4996 at using std::fill_n

Reported by: Yury Podpruzhnikov <QWERTYura@…> Owned by: No-Maintainer
Milestone: To Be Determined Component: random
Version: Boost 1.58.0 Severity: Problem
Keywords: Cc:

Description

Problem

We develop project using msvc 2013.

Warning appear just after include <boost/random/mersenne_twister.hpp> During compilation debug version with default settings.

After compilation I take warning:

1>C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xutility(2715): warning C4996: 'std::_Fill_n': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'
1>          C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xutility(2701) : see declaration of 'std::_Fill_n'
1>          X:\xxx\boost_1_58_0\boost/random/detail/polynomial.hpp(126) : see reference to function template instantiation '_OutIt std::fill_n<boost::random::detail::polynomial_ops::digit_t*,size_t,boost::random::detail::polynomial_ops::digit_t>(_OutIt,_Diff,const _Ty &)' being compiled
1>          with
1>          [
1>              _OutIt=boost::random::detail::polynomial_ops::digit_t *
1>  ,            _Diff=size_t
1>  ,            _Ty=boost::random::detail::polynomial_ops::digit_t
1>          ]

problem source code is:

    static void multiply(const digit_t * lhs, std::size_t lhs_size,
                         const digit_t * rhs, std::size_t rhs_size,
                         digit_t * output)
    {
        std::fill_n(SilenceMSVC_C4996(output), lhs_size + rhs_size, digit_t(0)); // <<<<<< problem line
        multiply_add(lhs, lhs_size, rhs, rhs_size, output);
    }

Cause

Warning appear because Visual C++ Checked Iterators is enabled. See https://msdn.microsoft.com/en-us/library/vstudio/aa985965%28v=vs.120%29.aspx.

This tecnology don't allow use pointer with std::fill_n (and others). And so we take warning.

Disable warning don't work!

Try disable warning.

// some std library
#include <map>
#include <algorithm>

#pragma warning(disable:4996)
#include <boost/random/mersenne_twister.hpp>

Warning is still exist. As I understand. MSVC think what warning appear in xutility (not in polynomial.hpp). Because if add #pragma at start of the program then warning will be disabled.

But disable this warning in xutility is wrong.

Decision

There is one case is described at MS article https://msdn.microsoft.com/en-us/library/vstudio/aa985965%28v=vs.120%29.aspx - using stdext::make_checked_array_iterator.

    // WARNING C4996: Pointers cannot be checked in debug mode
    // (an overrun will trigger undefined behavior)
    int a6[16];
    int * p6 = a6;
    transform(v.begin(), v.end(), p6, [](int n) { return n * 6; });
    print("a6: ", a6);

    // OK: stdext::checked_array_iterator is checked in debug mode
    // (an overrun will trigger a debug assertion)
    int a7[16];
    int * p7 = a7;
    transform(v.begin(), v.end(), stdext::make_checked_array_iterator(p7, 16), [](int n) { return n * 7; });
    print("a7: ", a7);

I wrote decision:

// Silence using pointer in std::find and others. >= Visual Studio 2013, debug.
#ifndef SilenceMSVC_C4996
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1800) && _ITERATOR_DEBUG_LEVEL != 0
#define SilenceMSVC_C4996(pointer) stdext::make_unchecked_array_iterator(pointer)
#else
#define SilenceMSVC_C4996(pointer) pointer
#endif
#endif

And replace calling std::fill_n with next code:

std::fill_n(SilenceMSVC_C4996(output), lhs_size + rhs_size, digit_t(0));

Other warning places

I also used this macros in:
boost\random\detail\polynomial.hpp:
static void mod_pow_x(boost::uintmax_t exponent, const digit_t * mod, std::size_t mod_bits, digit_t * out)

replace (2 times):

std::fill_n(out + 1, n - 1, digit_t(0));

to

std::fill_n(SilenceMSVC_C4996(out + 1), n - 1, digit_t(0));

In boost/algorithm/string/detail/classification.hpp:

replace:

::std::copy(::boost::begin(Range), ::boost::end(Range), Storage);

to

::std::copy(::boost::begin(Range), ::boost::end(Range), SilenceMSVC_C4996(Storage));}}}

Change History (1)

comment:1 by Steven Watanabe, 7 years ago

Resolution: wontfix
Status: newclosed

I'm not going to change correct code that the standard is explicitly designed to allow, just because msvc has unilaterally decided that it's bad.

Note: See TracTickets for help on using tickets.