本文最后更新于 2026-03-05,文章内容可能已经过时。

在C语言中,字符串拷贝应避免使用不安全的strcpy(因其不检查目标缓冲区大小,易导致缓冲区溢出),推荐使用strncpy(需控制复制长度并手动确保结尾\0)或strdup(需动态分配内存并手动调用free)进行安全操作,以有效预防安全漏洞。

在C语言中,字符串拷贝是基本操作之一,主要用于将一个字符串的内容复制到另一个字符串缓冲区中。C标准库提供了多种字符串拷贝函数,其中最常用的是strcpy,但也有更安全的替代方案。

1. strcpy 函数

基本信息

  • 功能:将源字符串(包括结尾的\0)复制到目标字符串
  • 头文件#include <string.h>
  • 函数原型char *strcpy(char *dest, const char *src);
  • 返回值:返回目标字符串的指针(dest

使用示例

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

int main() {
    char src[] = "Hello, World!";
    char dest[20];
    
    strcpy(dest, src);
    printf("复制后的字符串: %s\n", dest);
    
    return 0;
}

注意事项

  • 缓冲区溢出风险strcpy不检查目标缓冲区大小,如果目标空间不足,会导致缓冲区溢出,可能造成程序崩溃或安全漏洞
  • 目标缓冲区必须足够大:必须确保dest有足够的空间容纳src字符串(包括\0

2. strcpy的安全问题

缓冲区溢出问题

当源字符串长度超过目标缓冲区容量时,strcpy会继续写入,导致:

  • 程序崩溃
  • 未定义行为
  • 安全漏洞(可能被攻击者利用)

安全编码建议

  1. 确保目标缓冲区足够大:在使用前检查目标缓冲区大小
  2. 使用更安全的替代函数:如strncpystrlcpy
  3. 添加错误检查:在关键位置添加断言或条件检查

3. 替代安全函数

strncpy 函数

  • 功能:复制源字符串的前n个字符到目标字符串

  • 函数原型char *strncpy(char *dest, const char *src, size_t n);

  • 使用示例

    char src[] = "Hello, World!";
    char dest[10];
    
    strncpy(dest, src, sizeof(dest) - 1);
    dest[sizeof(dest) - 1] = '\0'; // 确保字符串以null结尾
    

strdup 函数

  • 功能:复制字符串到新分配的内存中

  • 函数原型char *strdup(const char *s);

  • 使用示例

    char *s = "Hello, World!";
    char *d = strdup(s);
    if (d != NULL) {
        printf("%s\n", d);
        free(d); // 使用后必须释放内存
    }
    

memcpy 函数

  • 功能:按字节复制内存块(可用于字符串,但不自动处理\0

  • 函数原型void *memcpy(void *dest, const void *src, size_t n);

  • 使用示例

    char src[] = "Hello, World!";
    char dest[20];
    memcpy(dest, src, strlen(src) + 1); // 包含结尾的'\0'
    

4. 自定义实现 strcpy

如果不使用标准库函数,可以自己实现:

#include <assert.h>

char *my_strcpy(char *dest, const char *src) {
    char *r = dest;
    assert(dest != NULL);
    assert(src != NULL);
    
    while ((*r++ = *src++) != '\0');
    
    return dest;
}

5. 推荐实践

  1. 避免使用strcpy:在安全要求高的项目中,建议完全避免使用strcpy,可以定义:

    #define strcpy Unsafe_strcpy
    

    这样编译时会报错,强制使用更安全的函数

  2. 优先使用strncpy:当需要控制复制长度时,使用strncpy并确保正确处理结尾\0

  3. 使用strdup:当需要动态分配内存时,使用strdup并记得用free释放

  4. 使用C11标准的strlcpy:在支持C11的系统中,strlcpy提供更安全的字符串拷贝

总结

函数安全性说明适用场景
strcpy不检查缓冲区大小不推荐使用
strncpy限制复制长度,但需手动处理\0需要控制长度的场景
strdup自动分配内存,需手动释放需要动态分配内存的场景
memcpy通用内存拷贝,不处理字符串结束符需要精确控制字节数的场景

在C语言编程中,字符串拷贝是常见操作,但必须注意安全问题。选择合适的函数并正确使用,可以避免许多潜在的程序错误和安全漏洞。