memcpy、strcpy 拷贝安全吗?

结论:都不安全!
strcpymemcpy 都是C语言标准库中不安全的内存拷贝函数,它们不会检查目标缓冲区大小,极易造成缓冲区溢出,导致程序崩溃、数据篡改、安全漏洞(黑客攻击)。

下面我给你讲清楚两者的区别、风险、以及正确的安全替代方案。


一、先搞懂两个函数的作用

1. strcpy —— 字符串拷贝

char* strcpy(char* dest, const char* src);
  • 只用于字符串,遇到 \0 才停止
  • 不检查目标缓冲区大小
  • 风险:源字符串过长 → 覆盖目标内存 → 缓冲区溢出

2. memcpy —— 内存块拷贝

void* memcpy(void* dest, const void* src, size_t n);
  • 通用内存拷贝,不关心内容,不管 \0
  • 必须手动指定拷贝长度 n
  • 风险n 大于目标缓冲区大小 → 内存越界 → 崩溃/漏洞

二、为什么不安全?(核心风险)

1. 共同致命问题

都不验证目标缓冲区是否足够大
都可能导致内存越界写入
都是高危安全漏洞(CWE-120 缓冲区溢出)

2. 各自坑点

  • strcpy 坑:依赖 \0 结束,漏写 \0 会乱拷贝,且完全不限制长度
  • memcpy 坑:长度由程序员手动控制,算错长度就直接越界

三、不安全代码示例(一看就懂)

1. strcpy 溢出

char buf[5];        // 只能存 4 个字符 + \0
strcpy(buf, "hello world");  // 超长!直接越界写内存

2. memcpy 溢出

char buf[5];
char data[] = "123456789";
memcpy(buf, data, 10);  // 拷贝10字节 → 越界!

后果:程序崩溃、堆栈破坏、数据被篡改、远程代码执行漏洞。


四、安全替代函数(必须用这些!)

1. 字符串安全拷贝 → strncpy / snprintf

推荐:snprintf(最安全、最常用)

snprintf(dest, 目标缓冲区大小, "%s", src);
  • 自动限制长度
  • 一定会保证结尾加 \0
  • 绝对不会溢出

示例:

char buf[5];
snprintf(buf, sizeof(buf), "%s", "hello world");
// 结果:buf = "hel\0"(安全截断)

2. 内存安全拷贝 → memmove / memcpy_s

  • memmove:比 memcpy 多支持内存重叠情况,更安全
  • memcpy_s:C11 安全标准函数,强制检查长度、空指针

最通用安全写法:

memcpy(dest, src, 要拷贝的长度 <= 目标缓冲区大小 ? 要拷贝的长度 : 目标缓冲区大小);

五、快速对比表

函数 用途 安全吗 最大问题
strcpy 字符串拷贝 ❌ 不安全 不检查长度,溢出
memcpy 内存拷贝 ❌ 不安全 手动算长度,易越界
snprintf 字符串拷贝 ✅ 安全 自动截断,补 \0
memmove 内存拷贝 ✅ 较安全 支持内存重叠
strncpy 字符串拷贝 ⚠️ 半安全 可能不补 \0

总结

  1. strcpymemcpy 都不安全,禁止在新项目中使用
  2. 字符串拷贝用 snprintf(最安全)
  3. 内存拷贝用 memmove 或带长度校验的 memcpy
  4. 核心安全原则:拷贝前必须检查:目标缓冲区 ≥ 拷贝长度
Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐