C语言+安全函数+非安全函数
在C语言中,许多标准库函数(如 strcpy
、scanf
、gets
等)由于缺乏边界检查,容易导致 缓冲区溢出(Buffer Overflow)、内存越界访问 等安全问题。为了解决这些问题,C11标准引入了 安全函数(Safe Functions),同时一些编译器(如MSVC、GCC)也提供了替代方案(如 _s
后缀函数或 strlcpy
)。
例如,当我们将一个字符串要赋值到另一个数组中时,我们一般会使用C语言自带的strcpy函数,但是针对该函数的底层实现,仅仅只是傻瓜式的将源地址的数据存储到目的地址,不会注意缓冲区是否溢出,如果目的地址空间不够,那么相邻的地址的值会被改变,然后读取的数据不对,严重的可能会造成程序崩溃。
#include <stdio.h>
#include <string.h>int main()
{char *str = "This is a test string";char dest[10],dest2[10];printf("dest addr = %p\n", dest);printf("dest2 addr = %p\n", dest2);strcpy(dest2, str); // 溢出导致未定义行为printf("dest str: %s\n", dest);printf("dest2 str: %s\n", dest2);return 0;
}
因此,为了规避上述问题,C11标准定义了 边界检查接口(Bounds-checking interfaces),函数以 _s
后缀标识,需传递目标缓冲区大小。例如采用下面的安全函数进行赋值,那么只会赋值失败,不会有什么其他的危险
#include <stdio.h>
#include <string.h>int main()
{char *str = "This is a test string";char dest[10];printf("dest addr = %p\n", dest);if (strcpy_s(dest, sizeof(dest), str) == 0) {printf("Copied: %s\n", dest);} else {printf("Copy failed: buffer too small\n");}return 0;
}
除开上面的strcpy有安全函数外,还有其他函数也具有边界安全函数
函数 | 作用 | 示例 |
---|---|---|
strcat_s | 安全拼接字符串 | strcat_s(dest, sizeof(dest), src) |
scanf_s | 安全格式化输入 | scanf_s("%9s", buf, sizeof(buf)) |
memcpy_s | 安全内存复制 | memcpy_s(dest, sizeof(dest), src, n) |
总体来说,安全函数的核心:通过显式传递缓冲区大小防止溢出。而这更重要的一点就是始终检查边界、验证输入、启用编译器警告,需要让代码做到0警告,以后调用一些C语言函数时,可以先了解一下是否有安全函数,如果有就可以直接用,虽然这是一个小问题,但是会无意间增加代码的鲁棒性。