您的位置:首页 > 其它

关于调用strcpy()函数时总是报错问题,5种方法解决!

2016-02-25 17:09 417 查看
【问题】

只要调用strcpy()函数在程序运行时,总是出现错误:

error C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

【原因】

因为这个函数是不安全,可能造成缓冲区溢出!

【常用方法】

1、新建项目时不要勾选安全开发生命周期检查

2、把strcpy换成strcpy_s

3、在文件开头加上 #define _CRT_SECURE_NO_WARNINGS

这三种方法一般也会出现其他问题。

【最好的解决方法】

1、每次调用strcpy函数时在文件开头 加上#pragma warning(disable:4996)。此方法比较直接有效。

2、在项目属性C/C++预处理器中加上 _CRT_SECURE_NO_WARNINGS。

打开项目,右键属性,如图:编辑点开,添加一行_CRT_SECURE_NO_WARNINGS就行。此方法永久解决问题



【实例】

#include<iostream>

#include<cstring>

#pragma warning(disable:4996)

using namespace std;

int main()

{

int i;

cin >> i;

char buf[7][10];//{"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};

strcpy(buf[0], "Sunday\0");

strcpy(buf[1], "Monday\0");

strcpy(buf[2], "Tuesday\0");

strcpy(buf[3], "Wednesday\0");

strcpy(buf[4], "Thursday\0");

strcpy(buf[5], "Friday\0");

strcpy(buf[6], "Saturday\0");

if (i>7 || i<0)

{

cout << "Input Error" << endl;

return 0;

}

else

cout << buf[i] << endl;

system("pause");

return 1;

}

【下附官方解读原因】

“function”: 也被声明为否决 的 “std::<函数名>”: 具有可能不安全的参数的函数调用 - 此调用依靠调用方检查传递的值是否正确。若要禁用此警告,请使用 -D_SCL_SECURE_NO_WARNINGS。请参阅有关如何使用
Visual C++“经过检查的迭代器”的文档

此警告/错误有许多可能的含义。

C4996 可能会发生,因为编译器遇到了标记有 deprecated 的函数。在未来版本中可能不再支持此函数。可以用 warning 杂注关闭此警告(如下例所示)。

为了支持新的、更安全的函数,否决了某些 CRT 和标准 C++ 库函数。有关要改用的函数的更多信息,请参见错误消息中被否决的函数的文档。若要关闭 CRT 否决警告,请定义 _CRT_SECURE_NO_WARNINGS。有关不推荐使用的函数的更多信息,请参见 CRT
中的安全功能和安全库:C++ 标准库

如果你在 std 命名空间中使用 <hash_map><hash_set> 头文件的成员,你将会看到 C4996。有关更多信息,请参见 stdext
命名空间。

如果出于安全原因使用了否决的 MFC 或 ATL 函数,也可能发生 C4996。若要取消这些警告,请参见 _AFX_SECURE_NO_WARNINGS_ATL_SECURE_NO_WARNINGS

在使用封送处理库时也可能会发生 C4996。在这种情况下,C4996 是错误,而非警告。使用 marshal_as 在需要 marshal_context
类的两种数据类型之间进行转换时,将发生此错误。如果封送处理库不支持转换,您也会收到此错误。有关封送处理库的更多信息,请参见 C++
中的封送处理概述。

在第一个示例中,为在其中声明了函数的行和在其中使用了函数的行生成 C4996

下面的示例生成 C4996。

C++

// C4996.cpp
// compile with: /W3
// C4996 warning expected
#include <stdio.h>

// #pragma warning(disable : 4996)
void func1(void) {
printf_s("\nIn func1");
}

__declspec(deprecated) void func1(int) {
printf_s("\nIn func2");
}

int main() {
func1();
func1(1);
}


如果在使用定义的 _ITERATOR_DEBUG_LEVEL(对于调试模式生成,默认情况下设置为 1)进行编译时未使用经过检查的迭代器,也可能发生 C4996。有关更多信息,请参见经过检查的迭代器

以下 STL 代码示例生成 C4996。

C++

// C4996_b.cpp
// compile with: /EHsc /W3 /c
#define _ITERATOR_DEBUG_LEVEL 1

#include <algorithm>
#include <iterator>

using namespace std;
using namespace stdext;

int main() {
int a[] = { 1, 2, 3 };
int b[] = { 10, 11, 12 };
copy(a, a + 3, b + 1);   // C4996
// try the following line instead
//   copy(a, a + 3, b);
copy(a, a + 3, checked_array_iterator<int *>(b, 3));   // OK
}


下面的 STL 代码示例生成 C4996 作为警告。注释是内联的。

C++

#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
#include <numeric>
#include <string>
#include <vector>

using namespace std;

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

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

cout << endl;
}

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

// OK: vector::iterator is checked in debug mode
// (i.e. an overrun will trigger a debug assertion)
vector<int> 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<int> 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 will trigger a debug assertion)
array<int, 16> 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 will trigger a debug assertion)
// NOTE: This applies only when raw arrays are given to STL 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 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
// (i.e. 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);

// WARNING SILENCED: stdext::unchecked_array_iterator is marked as checked in debug mode
// (i.e. it performs no checking, so an overrun will trigger 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);
}


下面的示例生成 C4996,因为封送处理库需要上下文才能从 System::String 转换为 const char *。

C++

// C4996_Marshal.cpp
// compile with: /clr
// C4996 expected
#include <stdlib.h>
#include <string.h>
#include <msclr\marshal.h>

using namespace System;
using namespace msclr::interop;

int main() {
String^ message = gcnew String("Test String to Marshal");
const char* result;
result = marshal_as<const char*>( message );
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: