与内存有关的那些事儿

本文探讨了C++中使用strcpy与strcpy_s复制字符串时的安全性问题,并介绍了如何通过try...catch机制有效管理内存,避免内存泄漏。

这日,我写下如下代码:

#include <iostream>

int main(void)

{

       char *p = new char[5];

       char *t = new char[5];

       strcpy(t, "Hello");

       strcpy(p, t);

       std::cout<<p<<std::endl;

       delete [] p;

       delete [] t;

       system("pause");

       return 0;

}

   看了看,基本没问题,心想万事大吉,编译一下,可问题却出来了:

warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

warning C6211: 由于出现异常,正在泄漏内存“p”。应考虑使用局部 catch 块清理内存: Lines: 5, 6

warning C6386: 缓冲区溢出: 访问“参数 1时,“5*1个字节可写,但可能写入了“6个字节: Lines: 5, 6, 8

   出现4个警告,仔细看看,前2个属于同一个问题,第3个问题包含2个问题,但也属于同一类,第4个问题仔细看看,也是和第一个问题一样,是strcpy的问题;

   我纳闷,这个怎么会出现问题?看看它的提示,出现缓冲区溢出,再翻翻MSDN,上面这样写着:

The strcpy_s function copies the contents in the address of strSource, including the terminating null character, to the location specified by strDestination. The destination string must be large enough to hold the source string, including the terminating null character. The behavior of strcpy_s is undefined if the source and destination strings overlap.

If strDestination or strSource is a null pointer, or if the destination string is too small, the invalid parameter handler is invoked as described in Parameter Validation. If execution is allowed to continue, these functions  return EINVAL and set errno to EINVAL.Upon successful execution, the destination string will always be null terminated.

   大体瞄了几眼,大体意思是说strcpy_s会尽显缓冲区溢出检测,如果有问题,则抛出一个异常,而strcpy则可能不会抛出异常但会导致程序错误,也有可能由于非法访问而抛出异常。

   4个警告已经说明程序存在缓冲区溢出,所以strcpy会出现异常。

   再来看看第3个问题,警告说

       char *p = new char[5];

       char *t = new char[5];

   存在内存泄露,再看看MSDN,上面写道:

警告 C6211:由于出现异常,正在泄漏内存 <pointer>。应考虑使用局部 catch 块清理内存,此警告意味着在引发异常时未释放已分配的内存。位于路径末尾的语句可能会引发异常。

也就是说,编译器检测到程序会泄露内存,所以建议使用try...catch来清理内存。

    问题终于搞明白了,于是开始动手,代码改为如下:

#include <iostream>

int main(void)

{

       char *p = NULL;

       char *t = NULL;   

       try

       {    

              p = new char[6];

              t = new char[6];

              strcpy_s(t, 6, "Hello");

              strcpy_s(p, 6, t);

              std::cout<<p<<std::endl;

              delete [] p;

              delete [] t;

       }

       catch(std::bad_alloc &bad)

       {

              std::cout<<bad.what()<<std::endl;

              if (NULL != p)

              {

                     delete [] p;

              }

              if (NULL != t)

              {

                     delete [] t;

              }

       }

       system("pause");

       return 0;

}

   编译一下,OK,通过,运行,结果正确,问题解决。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值