最近更新于 2023-03-05 10:37

环境

Windows SDK 10.0(Windows 11)
平台工具集:Visual Studio 2022 v143
C 语言标准:C17
字符集:Unicode


Debian 11(arm64)
编译器:GNU(gcc)10.2.1
C 语言标准:C17
编译参数:-std=c17 -no-pie -Wall -Werror=return-type -Werror=address -Werror=sequence-point -Werror=format-security -Wextra -pedantic -Wimplicit-fallthrough -Wsequence-point -Wswitch-unreachable -Wswitch-enum -Wstringop-truncation -Wbool-compare -Wtautological-compare -Wfloat-equal -Wshadow=global -Wpointer-arith -Wpointer-compare -Wcast-align -Wcast-qual -Wwrite-strings -Wdangling-else -Wlogical-op -Wconversion -g -O0

问题描述

之前我是基本没怎么用 VS 的(MSVC 编译器),只是前段时间开始学 Windows API 才比较多的使用。
昨天晚上调试程序的时候遇到一个警告,情景类似下面的代码

#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <stdio.h>

int main()
{
    WCHAR s1[128];
    PCWSTR s2 = L"你好,世界!ABCDabcd1234";
    memset(s1, 0, sizeof(s1));
    wcsncpy(s1, s2, wcslen(s2));
    wprintf(L"%I64u\n", wcslen(s1));
}

file

然后在查阅微软技术文档中找到了解释

C6053
file
file

C6054
file

而记忆中使用 gcc 编译器并没有遇到过这种警告,所以在 gcc 下又试了一下

#include <stdio.h>
#include <string.h>

int main()
{
    char s[128];
    const char *a = "你好,世界!ABCDabcd1234";
    memset(s, 0, sizeof(s));
    strncpy(s, a, strlen(a));
    printf("%lu\n", strlen(s));
}

file

gcc 并没有警告这个,如果真的警告了这个,那肯定得给出替代方案。MSVC 警告了就在推荐它的 _s 安全函数作为替代,而且上面的文档也说了“可能”,并不是代码真的有问题,只是潜在问题。所以最终的关键就是看开发者能不能正确使用,要保证被复制的字符串长度不超过字符数组的容量,就不会发生溢出,也就并不需要使用安全函数。
在微软的努力下,C11 标准中加入了安全函数(可选实现),然而实际正面支持的就是 MSVC 自己吧。

作者 IYATT-yx