strcpy 会越界写入,因不检查目标缓冲区大小,若源字符串长度加1超过目标空间,将覆盖相邻内存,导致崩溃或安全漏洞;仅当确定 strlen(src)+1 ≤ dest 容量时才可使用。

strcpy 会越界写入,不检查目标缓冲区大小
直接用 strcpy 拷贝字符串,等于把源字符串(包括结尾的 \0)原样塞进目标内存——它完全不管目标空间够不够。一旦 src 比 dest 能容纳的多,就会往后面乱写,轻则覆盖相邻变量,重则触发段错误或安全漏洞。
- 常见错误现象:
strcpy(dest, "hello world");中dest只有 5 字节,程序运行时崩溃或行为异常 - 使用场景:仅限你 100% 确认
strlen(src) + 1 ,比如静态数组且长度可控 - 参数差异:
strcpy只有两个参数:char* dest和const char* src,不接受长度限制
strncpy 不自动补 \0,容易导致字符串未终止
strncpy 看似安全,但它的设计反直觉:当 src 长度 ≥ n 时,它只拷贝前 n-1 个字符,然后**不写 \0**;只有 src 更短时才用 \0 填满剩余空间。结果就是,很多代码漏掉手动补 \0,后续用 printf 或 strlen 就读到垃圾内存。
- 常见错误现象:
char buf[10]; strncpy(buf, "hello world", sizeof(buf)-1); printf("%s", buf);输出乱码或卡死 - 使用场景:适合固定长度日志字段、协议头等需严格字节对齐的场合,但必须自己确保末尾是
\0 - 性能影响:即使
src很短,strncpy仍会把剩余空间全填\0,有隐式零初始化开销
C++ 里优先用 std::string,别碰这些 C 风格函数
现代 C++ 几乎没理由手管字符数组。用 std::string 自动管理内存、支持拷贝赋值、可拼接可比较,还不会越界——str2 = str1; 这一行就干掉了所有 strcpy/strncpy 的风险和胶水代码。
- 兼容性影响:C 接口(如系统调用、老库)仍需
const char*,这时用str.c_str()安全取值,但别拿它去改内容 - 容易踩的坑:把
std::string的内部指针存起来长期用,string一 resize 就悬空 - 如果非要用 C 风格操作,至少用
snprintf替代:snprintf(buf, sizeof(buf), "%s", src);——它保证末尾有\0,且不超界
Windows 下 strcpy_s 是微软扩展,跨平台项目慎用
strcpy_s 确实强制检查目标大小并保证 <p><code>strcpy_s 确实强制检查目标大小并保证 \0 终止,但它不是 C/C++ 标准函数,Linux/macOS 默认不提供。GCC/Clang 编译直接报 undefined reference,除非加宏或换 libc 实现。
undefined reference,除非加宏或换 libc 实现。
立即学习“C++免费学习笔记(深入)”;
- 错误信息:
error: 'strcpy_s' was not declared in this scope - 使用场景:纯 Windows 桌面应用且明确启用 SAL 注解时可考虑,否则增加维护成本
- 替代方案:用
std::string或封装一层带长度检查的 memcpy + 手动置\0
C 字符串拷贝真正的复杂点不在函数怎么选,而在于「谁负责分配、谁负责释放、谁保证长度一致」——这三个问题没理清,换哪个函数都只是把崩溃延迟几行代码而已。










