Visual Studio中strcpy_s的异常行为及-2值来源探究
关于strcpy_s行为与-2值来源的解析
环境与测试代码
平台:Win11、Visual Studio 2022
测试代码:
#include <stdio.h> #include <string.h> int main() { char ori[5] = { 'a', 'b', '\0', 'c', 'd' }; //char *safe = malloc(10 * sizeof(char)); //char *unsafe = malloc(10 * sizeof(char)); char safe[10]; char unsafe[10]; memset(safe, 0, 10 * sizeof(char)); memset(unsafe, 0, 10 * sizeof(char)); strcpy(unsafe, ori); strcpy_s(safe, 10, ori); printf("SAFE: %c\n", safe[3]); printf("UnSafe: %c\n", unsafe[3]); return 0; }
问题现象
初始化后safe和unsafe数组均为全0,执行strcpy和strcpy_s后,预期两个数组都会变成{'a','b','\0','\0','\0','\0','\0','\0','\0','\0'},但实际safe数组为{97,98,0,-2,-2,-2,-2,-2,-2,-2}。
strcpy_s的具体行为
strcpy_s是C标准库为提升安全性设计的字符串拷贝函数,相比strcpy多了两项关键操作:
- 校验目标缓冲区长度是否足够容纳源字符串(含终止符
\0),长度不足时会触发错误处理(默认可能直接终止程序,取决于编译器设置)。 - 源字符串拷贝完成后,会将目标缓冲区剩余未使用的字节填充为特定“毒药值”——这是Visual Studio实现的特性,用于辅助开发者检测内存越界访问或未初始化内存的使用问题。
-2值的来源
你看到的-2对应十六进制0xFE,是微软编译器定义的毒药值。这个值用来标记“已初始化但未被正常使用的内存”,目的是让开发者在调试时快速发现异常:如果程序意外访问到这些填充值,就能立刻意识到可能存在逻辑漏洞。
在你的测试中,ori含终止符共占3字节,safe缓冲区长度为10字节,拷贝完成后剩余的7字节(索引3到9)就被填充为0xFE(十进制-2)。而strcpy没有填充逻辑,剩余字节保持初始的0值。
内容的提问来源于stack exchange,提问作者Zhou Jia
相关产品推荐
相关产品推荐

