错误C4996

1. 解决方法:

在项目处右键点击找到属性;
点击配置属性;
点击C/C++在右侧找到SDL检查点击最右端小箭头,将其改成否。


下面这个好像是第二种解决方法
项目-->项目属性-->C/C++-->预处理器定义
添加:_CRT_NONSTDC_NO_DEPRECATE和_CRT_SECURE_NO_WARNINGS

我也不知道为什么之前写的博客里面东西变了...
大家按照上面第一个方法改掉就行了

解决方法:
#pragma warning(disable:4996)

2. 问题出现原因:

创建项目时,会有一个勾选项,叫做“安全开发生命周期(SDL)检查”,这个东西是微软在VS2012新推出的东西,为了是能更好的监管开发者的代码安全,如果勾选上这一项,那么他将严格按照SDL的规则编译代码,会有一些以前常用的函数无法通过编译,比如在VS2010中的scanf是warning那么在VS2012中就是error了。
  
若要在 Visual Studio 中定义预处理器宏:
打开你的项目属性页对话框,展开配置属性 > C/c + + > 预处理器,在中预处理器定义属性,添加宏名称。 选择“确定” 进行保存,然后重新生成项目。
若要仅在特定源文件中定义的宏,请添加一个行如#define EXAMPLE_MACRO_NAME包含的头文件的任意行之前。

以下内容来源于Microsoft Visual Studio 2017

这些是由 C 运行时库和标准库,但未详尽列出生成的一些常见 C4996 消息:
1:POSIX 函数名称
  此项的 POSIX 名称已弃用。请改用与 ISO C 和 c + + 一致的名称: new_name。 请参阅联机帮助了解详细信息。
  Microsoft 已重命名以符合 C99 和 c++03 规则的实现定义的全局函数名称的 CRT 中的一些 POSIX 函数。 仅原始 POSIX 名称已弃用,而不是函数本身。 在大多数情况下,前导下划线已添加到 POSIX 函数名称,以创建符合标准的名称。 编译器会发出弃用警告的原始函数名称,并建议首选的名称。
  若要解决此问题,我们通常建议更改代码以改为使用建议的函数名称。 但是,更新的名称是特定于 Microsoft 的。 如果您需要将现有的函数名称,用于可移植性原因,可以关闭这些警告。 在其原始名称下的库中的 POSIX 函数现在仍然有效。
  若要关闭这些函数的弃用警告,请定义预处理器宏_CRT_NONSTDC_NO_WARNINGS。 可以通过包括选项定义此宏在命令行/D_CRT_NONSTDC_NO_WARNINGS。

2:不安全的 CRT 库函数   
  此函数或变量可能不安全。请考虑使用 safe_version 相反。若要禁用弃用,请使用_CRT_SECURE_NO_WARNINGS。请参阅联机帮助了解详细信息。Microsoft 已弃用某些CRT 和 c + + 标准库函数和全局变量以支持更多安全版本。
   在大多数情况下,已弃用的函数允许未选中状态的读取或写入访问权限可能会导致严重的安全问题的缓冲区。
   编译器会发出对这些函数的弃用警告,并建议首选函数。   若要解决此问题,我们建议你使用的函数或变量safe_version相反。
  如果已验证不能为缓冲区覆盖或 overread 出现在你的代码,并且您不能更改的代码可移植性原因,您可以关闭该警告。若要关闭 CRT中的这些函数的弃用警告,定义 _CRT_SECURE_NO_WARNINGS。 若要关闭有关弃用的全局变量的警告,请定义 _CRT_SECURE_NO_WARNINGS_GLOBALS。
有关这些不推荐使用的函数和全局变量的详细信息,请参阅CRT 中的安全功能和安全库:C++标准库

3:不安全的标准库函数
  std::function_name ::_选中此项_迭代器::_Deprecate 调用到 std:: function_name 可能不安全的参数与此调用依靠调用方检查传递的值是否正确。若要禁用此警告,请使用-D_SCL_SECURE_NO_WARNINGS。有关如何使用Visual c + + Checked Iterators,请参阅文档
因为某些 c + + 标准库模板函数不会检查参数正确,在调试版本中会出现此警告。 在大多数情况下,这是因为没有足够的信息可供要检查容器边界的函数或使用该函数可能会错误地使用迭代器。此警告有助于标识这些函数用途,因为它们可能会在程序中的严重安全漏洞的源。 有关更多信息,请参见 CheckedIterators
  例如,会出现此警告在调试模式下如果传递到的元素指针std::copy而不是普通的数组。若要解决此问题,请使用正确声明的数组,因此库可以检查数组扩展盘区,并执行边界检查。

// compile with: cl /c /W4 /D_DEBUG C4996_copyarray.cpp
#include 

void example(char const * const src) {
   char dest[1234];
   char * pdest3 = dest + 3;
   std::copy(src, src + 42, pdest3); // C4996
   std::copy(src, src + 42, dest);   // OK, copy can tell that dest is 1234 elements } ```

多个标准库算法已更新,可以在 C + + 14 中有"双范围"版本。

如果您使用双范围版本,第二个范围提供了必要的边界检查: ```// C4996_containers.cpp // compile
with: cl /c /W4 /D_DEBUG C4996_containers.cpp
#include

bool example(
char const * const left,
const size_t leftSize,
char const * const right,
const size_t rightSize) {
bool result = false;
result = std::equal(left, left + leftSize, right); // C4996
// To fix, try this form instead:
// result = std::equal(left, left + leftSize, right, right + rightSize); // OK
return result; } ```

此示例演示几个标准库可用于检查迭代器使用情况的更多方法和未选中状态的使用情况可能存在危险:

C4996_standard.cpp
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

template  void print(const string& s, const C& c) {
    cout << s;

    for (const auto& e : c) {
        cout << e << " ";
    }

    cout << endl; }

int main() {
    vector v(16);
    iota(v.begin(), v.end(), 0);
    print("v: ", v);

    // OK: vector::iterator is checked in debug mode
    // (i.e. an overrun triggers a debug assertion)
    vector v2(16);
    transform(v.begin(), v.end(), v2.begin(), [](int n) { return n * 2; });
    print("v2: ", v2);

    // OK: back_insert_iterator is marked as checked in debug mode
    // (i.e. an overrun is impossible)
    vector v3;
    transform(v.begin(), v.end(), back_inserter(v3), [](int n) { return n * 3; });
    print("v3: ", v3);

    // OK: array::iterator is checked in debug mode
    // (i.e. an overrun triggers a debug assertion)
    array a4;
    transform(v.begin(), v.end(), a4.begin(), [](int n) { return n * 4; });
    print("a4: ", a4);

    // OK: Raw arrays are checked in debug mode
    // (i.e. an overrun triggers a debug assertion)
    // NOTE: This applies only when raw arrays are
    // given to C++ Standard Library algorithms!
    int a5[16];
    transform(v.begin(), v.end(), a5, [](int n) { return n * 5; });
    print("a5: ", a5);

    // WARNING C4996: Pointers cannot be checked in debug mode
    // (i.e. an overrun triggers 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
    // (i.e. an overrun triggers 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);

    // WARNING SILENCED: stdext::unchecked_array_iterator
    // is marked as checked in debug mode, but it performs no checking,
    // so an overrun triggers undefined behavior
    int a8[16];
    int * p8 = a8;
    transform( v.begin(), v.end(),
        stdext::make_unchecked_array_iterator(p8),
        [](int n) { return n * 8; });
    print("a8: ", a8); } ``

如果已验证您的代码不能具有缓冲区溢出错误在标准库函数,触发此警告,你可能想要关闭此警告。 若要关闭这些函数的警告,定义 _SCL_SECURE_NO_WARNINGS。

4:已过时的 CRT 函数和变量
此函数或变量已被较新的库或操作系统功能。请考虑使用 new_item相反。请参阅联机帮助了解详细信息。某些库函数和全局变量由于过时已弃用。 可能会在未来版本的库中删除这些函数和变量。编译器会发出对这些项的弃用警告,并建议首选备用项。   若要解决此问题,我们建议更改代码以使用建议的函数或变量。若要关闭这些项的弃用警告,定义 _CRT_过时_NO_WARNINGS。 有关详细信息,请参阅弃用的函数或变量的文档。

你可能感兴趣的:(C/C++学习笔记)