strcpy()函数被弃用的原因以及扩展

bug

VS2015环境下,显示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. 即使前面加了头函数文件cstring 也无济于事。

原因:vs准备弃用strcpy的,安全性较低,所以微软提供了strcpy_s来代替.如果继续使用strcpy的,那么只需要在函数体前面加上#pragma warning(disable:4996)就可以了。

strcpy_s(dest, bufsize, src);
bufsize为dest缓冲区最大长度。它与 strcpy 的不同在于,在它取得额外参数来决定目的缓冲区大小时,会因为发生溢位而出现错误,如此一来,就可以预防缓冲区溢位。

PS: 缓冲区溢位攻击

当前存入的数据量大于缓冲区的容量,可能导致栈帧指向原本的函数返回地址被覆盖,黑客利用一点,篡改进程运行时栈(比如指向shell脚本),从而改变程序的正常流向。

写出线程安全的strcpy()

线程安全:当多个线程访问某个方法时,不管你通过怎样的调用方式、或者说这些线程如何交替地执行,我们在主程序中不需要去做任何的同步,这个方法的结果行为都是我们设想的正确行为,那么我们就可以说这个方法是线程安全的。

参考:https://www.cnblogs.com/chenyg32/p/3739564.html

设计:

1,参数校验

2,链式编程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <assert.h>
#include <string.h>

// const 修饰 src,防止被修改
char * my_strcpy(char * dest, const char * src) {
// 空指针的检查
assert(src != nullptr && dest != nullptr);

char * ret = dest;
//一路赋值,直至终止符。
while ( (*dest++ = *src++) != '\0');

// 返回原始dest的值
return ret;
}
//返回dst的原始值,使得函数能够支持链式表达式
//如: char * strA = strcpy(new char[10],strB);
//即: char * strA = new char[10];

假如考虑dst和src内存重叠的情况,需要考虑直接按内存一位一位进行复制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//解决dest与src内存重叠, cnt = 复制个数   
char * my_memcpy(char * dest, const char * src, int cnt) {
// 空指针的检查
//宏 : 计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。
assert(src != nullptr && dest != nullptr);

char * ret = dest;

//内存覆盖:src<=dst<=src+strlen(src)
if (dest >= src && dest <= src + cnt - 1) {
//从高地址开始复制
dest = dest + cnt - 1;
src = src + cnt - 1;
while (cnt--)
*dest-- = *src--;
}
else {
//内存无覆盖,从低地址开始复制
while(cnt--)
*dest++ = *src++;
}

// 返回原始dest的值
return ret;
}

char * my_strcpy2(char * dest, const char * src) {
// 空指针的检查
assert(src != nullptr && dest != nullptr);

char * ret = dest;

//strlen仅仅计算字符个数,不包括最后的\0。
my_memcpy(dest, src, strlen(src) + 1);

// 返回原始dest的值
return ret;
}

内存覆盖时为什么要从高地址开始复制,往低地址走:

eg:

1
2
3
*s = "abc";
my_strcpy2(s+1, s);
//防止dst与src重叠,把'\0'覆盖了;
---------------- 本文结束 ----------------

本文标题:strcpy()函数被弃用的原因以及扩展

文章作者:Pabebe

发布时间:2021年08月24日 - 19:04:35

最后更新:2022年03月16日 - 19:47:35

原始链接:https://pabebezz.github.io/article/98352641/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

0%