Why am I getting these _SCL_SECURE_NO_WARNINGS messages?

Recently, a C++ developer asked why they were getting diagnostic messages for this code:

void example(char const * const src, char * const dest) {
    std::copy(src, src + 42, dest);
}

If you compile this file in debug mode, you’ll get a message like the following:

xutility(2350,1): warning C4996: 'std::copy::_Unchecked_iterators::_Deprecate': Call to 'std::copy' 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' _DEPRECATE_UNCHECKED(copy, _Dest); ^ xutility(2350): note: see declaration of 'std::copy::_Unchecked_iterators::_Deprecate' _DEPRECATE_UNCHECKED(copy, _Dest); .\test.cpp(4): note: see reference to function template instantiation '_OutIt std::copy<const char,char*>(_InIt,_InIt,_OutIt)> ' being compiled with [ _OutIt=char *, _InIt=const char * ] std::copy(src, src + 42, dest);

This is caused by the STL’s iterator debugging support. If you turn on debugging (with /MTd or /MDd), you’re asking the STL to check the size of the resulting range for you, and if you just give us a plain pointer, there’s no way for std::copy to tell where the end of the range is.

You can tell the STL where the end of the range is in a number of ways:

  1. If possible, you can pass std::copy a plain array. If you start with an array, we will see what the extent of the array is, and do appropriate bounds checking.

    // copy can now tell that dest is 1234 elements
    void example(char const * const src) { 
       char dest[1234]; std::copy(src, src + 42, dest);  
    }

  2. Several standard library algorithms received “dual range” versions in C++14. If you use the dual range versions, the second range already provides the necessary bounds checking:

    bool example(char const * const left, const size_t leftSize, char const * const right, const size_t rightSize) {
       // triggers warning 
       return equal(left, left + leftSize, right); 
       // OK 
       return equal(left, left + leftSize, right, right + rightSize); 
    } 

  3. You can back the destination with a standard container, such as string or vector. If _ITERATOR_DEBUG_LEVEL is not zero, the iterator has enough information to know where it ends and provide appropriate bounds checking.
  4. You can use stdext::make_checked_array_iterator to create an iterator that knows the destination size.
  5. You can decide to accept the risk of exploitable bugs in your code in this area, and define _SCL_SECURE_NO_WARNINGS in your project, or before including any STL headers. With this setting, the STL will bounds check where it can, but will not warn you when it is unable to do so.

Have a question you want us to write up? Other feedback about this post or content you want to see (like a C++ tutorial on a specific scenario)? Leave it as a comment or email Eric (ebattali@microsoft.com). Thanks!