StrcpyC语言的函式之一,来自 C语言标准函式库,定义于 string.h,它可以复制以 null 为结束字元的记忆体区块到另一个记忆体区块内。由于字串在 C 语言不是首要的资料型态,而是以实作的方式来替代,在记忆体内以连续的位元组区块组成,strcpy 可以有效复制两个配置在记忆体以指标回传的字串(字元指标或是字串指标)。

函式原型如下:[1]

#include<string.h>
char *strcpy(char *destination, const char *source);

传回值是 destination 字元阵列或是配置在记忆体的字元指标(或是字串指标)。

使用方式与实作

例如

char *str1 = malloc(LARGE_NUMBER);
char *str2 = malloc(LARGE_NUMBER);

fgets(str1, LARGE_NUMBER, stdin);
strcpy(str2, str1); /* 這行程式碼類似 str2 "=" str1 */

前两行程式码是先配置记忆体,经由 malloc 函式把配置完成的记忆体位址,传回给 str1str2。到了下一行程式码,指向 str1 的记忆体,会被使用者输入的字串填满。之后,复制 str1 字串到 str2 的记忆体区块内。虽然 str2 = str1 这个程式叙述可以出现类似的现象,但是它只能复制位址从 str1str2,让 str2 指向 str1 的记忆体,实际上也无法真正做到复制字串的动作。这就是 str1str2 两个指标都指向相同的记忆体区块位址。这相当于所谓的 shallow copy(浅复制)英语Object copy,因为 str2 实际上没有真正从 str1 复制到字串,所以这两个指标所指的其实都是同一个的字串。

strcpy 函式利用回圈动作逐次完成复制字串中每一个字元。在GCC-4.8.0的testsuite中的实现如下:

extern void abort (void);
extern int inside_main;

__attribute__ ((__noinline__))
char *
strcpy (char *d, const char *s)
{
  char *r = d;
#if defined __OPTIMIZE__ && !defined __OPTIMIZE_SIZE__
  if (inside_main)
    abort ();
#endif
  while ((*d++ = *s++));
  return r;
}

缓冲区溢位

必须注意使用 strcpy 函式,因为如果来源字串的长度太长,当复制到目的缓冲区时,它会覆写到连接目的缓冲区后方的记忆体,导致无法预期的结果。而且程式通常容易会出现区段错误(也就是常见的例外现象),但是熟练的骇客会利用缓冲区溢位来破解进入作业系统(详见电脑安全)。

Bounds checking variants

strncpy 这个常见的 bounded variant 它的实作方式与 strcpy 相类似,它只要复制指定的位元组个数,而且只要它接近指定的最大长度时,就会在目的缓冲区加上结束字元来结束复制动作。只要指定的位元组个数大于目的字串的长度,它就会因为缓冲区溢位而受到影响;然而,程式会自动假定来源字串是以 null 作为结束字元的字串,当来源字串的长度大于指定的长度时,它无法保证产生出来的结果是以 null 来作为结束字元的字串,它也可能出现读取例外的现象。

strlcpy

OpenBSD 的研发人员 Todd C. MillerTheo de Raadt 两人设计 strlcpy 函式,通常视为是 strncpy 安全版本。对于一些作业系统而言,这个函式会出现被掌控的问题,但是它已经被 glibc 维修人员给特别地删除,所以在此建议使用 memcpy 函式来替代。[2]

strcpy_s

strcpy_s 函式是 strcpy 的安全版本,属于 ISO/IEC TR 24731 的标准, [3][4]某些 C 函式库支援这个函式,包含 Microsoft C Runtime Library(微软 C 语言执行时期函式库)。[5] 它与 strcpy 的不同在于,在它取得额外参数来决定目的缓冲区大小时,会因为发生溢位而出现错误,如此一来,就可以预防缓冲区溢位。由于 strcpy_s 对于 C 语言来说是新的函式,所以没有特别受到广泛支援。

反对Microsoft人士宣称,这个函式连同其他Microsoft在其Runtime Library号称对安全性所做的强化[6]皆为Microsoft试图把开发人员锁死在视窗平台上的手段之一。[7][8];虽然strcpy_s是属于ISO/IEC TR 24731的标准而非Windows独有的标准,且在本质上跟OpenBSD的strlcpy没有差别。

参考资料

  1. ^ 存档副本. [2007-06-11]. (原始内容存档于2007-06-10). 
  2. ^ libc-alpha mailing list页面存档备份,存于互联网档案馆), selected messages from 8 Aug 2000 thread: 53页面存档备份,存于互联网档案馆), 60页面存档备份,存于互联网档案馆), 61页面存档备份,存于互联网档案馆
  3. ^ ISO/IEC. ISO/IEC WDTR 24731 Specification for Secure C Library Functions. 国际标准化组织. 2004. 
  4. ^ Plakosh, Daniel. strcpy_s() and strcat_s(). Pearson Education, Inc. [2006-08-12]. (原始内容存档于2006-09-23). 
  5. ^ Microsoft. Security Enhancements in the CRT. MSDN. [2006-08-12]. 
  6. ^ Microsoft. Security Enhancements in the CRT. MSDN. [2008-09-16]. (原始内容存档于2008-09-13). 
  7. ^ Danny Kalev. They're at it again. InformIT. [2008-09-15]. (原始内容存档于2012-01-15). 
  8. ^ Security Enhanced CRT, Safer Than Standard Library?. [2008-09-15]. (原始内容存档于2008-09-19). 

外部链接