C++字符串拷贝与缓冲区溢出

对于常用的字符串拷贝函数,常用的有:

Ansi版本如下:

strcpy, strncpy, strcpy_s, strncpy_s, StringCbCopy

Unicode版本为:

wcscpy,wcsncpy,wcsncpy_s,wcsncpy_s,StringCbCopyW

其中最后一个为Windows的API,其余为c运行时函数。

这些函数完成的功能是一样的,然而本质上却有极大区别。

 

现在我们来看看这些函数分别如何工作。

为简化测试,我们只测试Ansi版本的函数。Unicde版本功能与之如出一辙。

测试代码如下(VS2005,多字节编码):

[cpp]  view plain copy
  1. char buff1[2] = {'1''/0'};  
  2. char buff2[2] = {'2''/0'};  
  3. strcpy(buff1, "1111111111111111");  
  4. strncpy(buff2, "abcdefghijklmnopqratuvwxyz", 2);  
  5. StringCbCopy(buff2, 2, "abcdefghijklmnopqratuvwxyz");  
  6. strcpy_s(buff2, 2, "abcdefghijklmnopqratuvwxyz");  

 

buff2的地址为0x22FE0C,内存分布如下图:

1

可以看到buff1和buff2之间被填充了0xcc,这是VS为了检测缓冲区运行时整的。

另外注意栈内存分配上的特点,后分配的buff2的地址在先分配的buff1地址之前。

 

 

现在执行strcpy,看内存变化:

2

strcpy强行把16字节写入了buff1为首的内存。然而系统没有任何反映,似乎一切正常。

然而,正式这种侥幸的正常,才会导致日后不可避免的缓冲区溢出导致的崩溃---谁知道buff1+2之后的14个字节是什么内容。

 

 

继续执行,看看strncpy的表现会不会好一点:

3

strncpy的第三个参数接收缓冲区大小,如果待拷贝字符串长度超过缓冲区,则截断超出的字符不拷贝。

这么做似乎很安全。然而致命的问题是这个“截断“太过劣质。

因为buff2失去了'/0'结束符,buff2字符串是从buff2开始直到之后内存中找到的第一个'/0'

在这里,由于buff2内存之后是buff1,buff2已经不再是2个字节的字符串了。缓冲区受到了破坏。

这个例子里,我们看到buff2的内容是形如"ab烫烫烫烫烫烫烫烫1111111111111111"这样的乱码

诚然,这样的操作也是极不安全的。

 

 

我们继续执行,看看StringCbCopy表现如何。

4

呼呼,我们终于看到一个表现堪称“不错”的字符串拷贝函数了。

她总算是“优美”的截断了过长的字符串,保证了缓冲区的安全性。

然而,这样的截断后的字符串是你需要的吗?比如一个路径名字符串被截断了,你还能用他来打开文件吗?

 

 

strcpy_s的第2个参数接收缓冲区大小。我们看看他执行结果如何:

5

饿...出现了assert错误。

不过这样对程序员来说应该是最好的,你很快能知道是哪里出了问题。

 

一般而言,凡是函数后面带有_s的字符串系列函数,都是微软整的“安全”字符串函数。

他会进行传入指针不为NULL、缓冲区足够大等等安全检查。

因此,我们在整字符串的时候,应该使用这些安全字符串。

 

最后请注意:上面所有函数都不进行内存重叠检查!请自己进行必要的内存重叠检查。


原文地址:http://blog.csdn.net/lsldd/article/details/4669888

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值