Visual C++: C4996 Warning on Copy with Array Parameters

Visual C++ throws a C4996 warning if std::copy is called with array parameters (instead of the conventional iterator parameters). For example, if you have code of the form:

std::copy( arr0, arr0 + 5, arr1 );

where arr0 and arr1 are pointers to arrays or valid memory locations.

The C4996 warning is of the form:

warning C4996: ‘std::_Copy_impl’: 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’

Visual C++ uses checked iterators by default everywhere for security reasons. This warning is a manifestation of that design decision. There are a few ways to deal with it:

  • checked_array_iterator: A checked_array_iterator can be used to wrap the unsafe array pointer. It is a Microsoft extension to the C++ Standard and is defined in the stdext namespace. It results in an assertion check at runtime, which throws an exception if it fails. Applying a checked_array_iterator on the above code:
    #include <iterator>
    std::copy( arr0, arr0 + 5, stdext::checked_array_iterator<int*>( arr1, 5 ) );
    
  • unchecked_copy: The copy call can be replaced with an unchecked_copy if you want to forgo the checking. This is defined in the stdext namespace. Note that this is usable in Visual C++ 2008 and not later. It was removed in Visual C++ 2010. Using unchecked_copy instead of copy:
    stdext::unchecked_copy( arr0, arr0 + 5, arr1 );
    
  • vector: Another solution is to wrap the destination array in a vector and use the vector as the destination of copy. Not a great solution, but it might work for you.
  • pragma warning: Turn off the C4996 warning for the call to copy using pragma warning. This can be applied at the source file level to mask all C4996 warnings. Note that this is a really bad move since it masks all deprecation warnings!
  • _SCL_SECURE_NO_WARNINGS: Define the _SCL_SECURE_NO_WARNINGS macro to turn off all C4996 warnings. SCL here stands for Standard C++ Library. Again, turning off this warning not a good move! If you want to do this anyway, add -D_SCL_SECURE_NO_WARNINGS to your project settings or #define _SCL_SECURE_NO_WARNINGS in your code.

Visual C++: Warning C4100

Warning 4100: unreferenced formal parameter might appear when C++ code is compiled at Warning Level 4 (/W4) with the Visual C++ compiler. For example, a function that generates C4100:

void Foo::OnEvent( const FooEvent& event )
{
    return;
}

There are a few ways to deal with this warning:

  • If this warning made you aware that you had a redundant parameter, that is good! Remove the unused parameter from both the function declaration and the definition:
    void Foo::OnEvent()
    {
        return;
    }
    
  • If the function signature cannot be changed but you do not really use the parameter in the function body, then remove the parameter name, while retaining the parameter type:
    void Foo::OnEvent( const FooEvent& )
    {
        return;
    }
    
  • If you are playing around with the code in the function body and will need the parameter in the future, then comment the parameter temporarily:
    void Foo::OnEvent( const FooEvent& /* event */ )
    {
        // Some commented code that uses "event" parameter
        return;
    }
    
  • pragma warning directives can be used to disable the warning locally:
    #pragma warning( push )
    #pragma warning( disable: 4100 )
    void Foo::OnEvent( const FooEvent& event )
    {
        return;
    }
    #pragma warning( pop )
    
  • If you are having many such functions generating warnings and want to do nothing to fix them, then use a pragma warning directive over the entire source file:
    // Foo.cpp
    #pragma warning( disable: 4100 )  // Disable for entire source file Foo.cpp
    
    void Foo::OnEvent( const FooEvent& event )
    {
        return;
    }
    

A final note: Visual C++ 2010 does not seem to have this warning at all! It has been mysteriously removed without providing any reason 🙂

Visual C++: pragma warning

It is a good practice to compile code at the highest warning level available from the compiler. When the compiler reports warnings on the code, the code should be fixed so that it compiles with zero warnings. But, sometimes this is not possible, for example, if the source of the warnings are headers included from external libraries. Common C++ libraries like Boost and special libraries like CGAL (Computational Geometry Algorithms Library) are notorious for introducing hundreds of warnings when their header files are included.

In Visual C++, the #pragma warning compiler directive is an effective way to disable these specific warnings. There are many specifiers that can be specified with #pragma warning. Here are a couple that I find most useful:

Warnings that are reported have an identifier and a textual message. The identifier is of the form CXXXX, where XXXX is the warning number. The disable specifier can be used to disable a specific warning, say C1234:

#pragma warning(disable: 1234)

The disabling of warnings should be localized as much as possible. This can be done using the push and pop specifiers around the offending code.

#pragma warning(push)
#pragma warning(disable: 1234)
// Offending code that produces C1234 warning goes here
#pragma warning(pop)

#pragma warning directives can be placed in header files or in source files. When the directive needs to be used across an entire source file or many files, one can get lazy and place it in a header that is included in all these files. This is not a good practice since the warning will be disabled for all the source files that include that header now or in the future.

I prefer placing directives at the source file level, so that their effect is localized to the source file. If one is placing the directive at the source file, it should be put at the top, even above the header files inclusion, to be effective:

// Foo.cpp
#pragma warning(disable: 1234)
#include "Foo.h"

Foo::Foo()
{ /***/ }