【C语言】strcpy函数的缺点

用法

这是C语言里面复制字符串的库函数, 函数声明包括在专门处理字符串的头文件<string.h>中:

char * strcpy( char * dst, const char * src );

这个函数把字符串src复制到一分配好的字符串空间dst中,复制的时候包括标志字符串结尾的空字符一起复制。操作成功,返回dst,否则返回NULL.

需要注意的问题

函数里的局部变量一般都是按序排放的,并且因为是分配在堆栈之中,它们的地址是向下“增长”,即向低地址方向增长。比如下面的程序:

   int flag=0x12345678;
   printf("%x\n",flag);

   char s[6];
   printf("address of  flag:   %x\n",&flag);
   printf("address of array s: %x\n",s);
   strcpy(s,"my aaaa");

   printf("%s\n",s);
   printf("%x\n",flag);
   printf("%c\n",*(char *)(&flag));//输出变量flag的第一个字节的内容

程序的运行结果:
12345678
address of flag: 28ff1c
address of array s: 28ff16
my aaaa
12340061
a
可以看出,程序执行时把变量flag分配的地址是0x28ff1c,而字符数组s的地址为0x28ff16,可以看到地址的增长方向是向下的,同时,s相对于flag的偏移量正好是字符数组s的大小,即6。在执行函数strcpy之前,可以把它们在内存中的布局表示如下(以字节为单位):在这里插入图片描述
若数据的字节序是小端模式(小端模式即是:数据的高位保存在内存的高地址,而地位保存在内存的低地址,大端模式倒过来的),所以对于变量flag,其高位为0x12保存在最高地址处,而其低位的0x78保存在其变量的起始处。这样的话,当执行函数strcpy(s,“my aaaa”)时,它会将从0x28ff16的地址处向上的连续的8个字节分别赋值为字符串“my aaaa”的每个字符(第8个字节是函数strcpy加上的一个字符串终止符0x00)。那么此时的内存情况如下:
在这里插入图片描述
可以看到,执行strcpy函数时,它会将变量flag的前两个字节也改写了!(图中红色的表示被改写的,即flag的第一个字节被重新赋值为了字符‘a’,第二个字节被赋值为终止符0x00)。为什么会这样?因为strcpy 函数不检查目的缓冲区的大小边界,而是将源字符串逐一的全部赋值给目的字符串地址起始的一块连续的内存空间,同时加上字符串终止符,会导致其他变量被覆盖。

所以最后输出变量flag时,其值变为0x12340061,即其高两字节未变,而最低位变为0x61即97,即字符a的ascii码,第二低字节变为0x00,即字符串终止符。

所以,使用strcpy时容易出错,不幸的是,这种bug是不易被发现的。所以需要格外的小心。为了避免出错,可以使用另一个具有相同功能的函数: strncpy,该函数可以指定要复制的字符串的长度。

猜你喜欢

转载自blog.csdn.net/Vcrossover/article/details/114711269