详述函数编写思路和流程

本次实现的strcpy_s函数需要实现以下功能:

a) 不会产生缓冲区溢出

b) 不产生无结尾的字符串

c) 不意外截断字符串

因此需要对输入字符串进行判断。

定义符号:

RSIZE_MAX 栈空间大小
s1 待复制空间
s1max 待复制字符串长度
s2 输入字符串
s1len 允许复制长度

对于需求a:需要比对s1max和RSIZE_MAX的大小,即比较申请的复制空间是否超出缓冲区限制,如果s1max > RSIZE_MAX就会发生栈溢出。

对于需求b和c:需要使得s1max > s1len,否则会发生空结尾错误或发生截断。如果s1max = s1len则没有给最后一位空值留出空间,发生空结尾错误。如果s1max < s1len会发生截断。

函数源代码

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
errno_t strcpy_s(char *s1, rsize_t s1max, const char *s2) {

if (s1 == NULL || s2 == NULL) {

return 1; // 无效的参数

}



if (s1max > RSIZE_MAX) {

return 2; // s1max 超过了允许的最大值

}

int s1len = strlen(s2); // 查找s2的长度,不超过s1max

if (s1len == s1max) {

return 3; // s2的长度与s1max相同,发生空结尾错误

}

if (s1len < s1max) {

strcpy(s1, s2);

return 0; // 复制成功

} else {

return 4; // s2的长度超过了s1max,会导致截断

}

}

运行结果需要截图证明(3种典型错误)

img

实验中第一次复制成功;

第二次字符串长于复制空间,会被截断;

第三次字符串长度=复制空间长度,发生空结尾错误;

最后一次申请的复制空间大于缓冲区空间(20),因此会发生缓冲区溢出。