这日,我写下如下代码:
#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,通过,运行,结果正确,问题解决。

http://blog.csdn.net/blpluto/article/details/4515748

与内存有关的那些事儿(数组分配空间不够,导致缓冲区溢出,从而strcpy会出现异常)的更多相关文章

  1. C语言malloc函数为一维,二维,三维数组分配空间

    c语言允许建立内存动态分配区域,以存放一些临时用的数据,这些数据不必在程序的声明部分定义,也不必等到函数结束时才释放,而是需要时随时开辟,不需要时随时释放,这些数据存储在堆区.可以根据需要,向系统申请 ...

  2. Java数组分配内存空间

    分配内存空间 数组名=new 数据类型[数组长度]: new关键字用来实现为数组或对象分配内存 数组具有固定的长度.获取数组的长度: 数组名.length 定义数组+分配内存空间 数据类型[]数组名= ...

  3. 06-01 Java 二维数组格式、二维数组内存图解、二维数组操作

    二维数组格式1 /* 二维数组:就是元素为一维数组的一个数组. 格式1: 数据类型[][] 数组名 = new 数据类型[m][n]; m:表示这个二维数组有多少个一维数组. n:表示每一个一维数组的 ...

  4. Java8内存模型—永久代(PermGen)和元空间(Metaspace)(转)

    Java8内存模型—永久代(PermGen)和元空间(Metaspace) 查看原文点击传送门:http://www.cnblogs.com/paddix/p/5309550.html 提示:本文做了 ...

  5. Java8内存模型—永久代(PermGen)和元空间(Metaspace)

    一.JVM 内存模型 根据 JVM 规范,JVM 内存共分为虚拟机栈.堆.方法区.程序计数器.本地方法栈五个部分. 1.虚拟机栈:每个线程有一个私有的栈,随着线程的创建而创建.栈里面存着的是一种叫“栈 ...

  6. (转)Java8内存模型—永久代(PermGen)和元空间(Metaspace)

    背景:介绍java8中永久代到元空间的转变. Java8内存模型—永久代(PermGen)和元空间(Metaspace) 一.JVM 内存模型 根据 JVM 规范,JVM 内存共分为虚拟机栈.堆.方法 ...

  7. 转:Java8内存模型—永久代(PermGen)和元空间(Metaspace)

    一.JVM 内存模型 根据 JVM 规范,JVM 内存共分为虚拟机栈.堆.方法区.程序计数器.本地方法栈五个部分. 1.虚拟机栈:每个线程有一个私有的栈,随着线程的创建而创建.栈里面存着的是一种叫“栈 ...

  8. Java8内存结构—永久代(PermGen)和元空间(Metaspace)

    本文转载 作者:liuxiaopeng 博客地址:https://www.cnblogs.com/paddix/p/5309550.html 一.JVM 内存结构 根据 JVM 规范,JVM 内存共分 ...

  9. 只要没有给String[]数组new 空间,那么他就只是一个引用

    public class Test1 { @Test public void test(){ String[] values = {"good", "morning&qu ...

随机推荐

  1. BZOJ 1877: [SDOI2009]晨跑( 最小费用最大流 )

    裸的费用流...拆点, 流量限制为1, 最后的流量和费用即答案. ------------------------------------------------------------------- ...

  2. 利用xshell密钥管理服务器远程登录+VIM dd命令操作之伤之再伤

    1.打开Xshell界面,中文界面方便操作,菜单栏:工具——新建用户密钥生成向导 2.密钥类型选择RSA,密钥长度选择2048位,单击下一步继续: 3.很快生成公钥对,单击下一步继续: 4.密钥名称可 ...

  3. Python 第七篇:异步IO\数据库\队列\缓存

    Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitMQ队列 Redis\Memcached缓存 Paramiko SSH Tws ...

  4. opencv开源库

    opencv是开源库 在Windows下编译扩展OpenCV 3.1.0 + opencv_contrib 为什么要CMake,这里我陈述自己的想法,作为一个刚使用opencv库的小白来说,有以下大概 ...

  5. docker学习笔记2:容器操作

    一.列出主机上已经创建的容器 docker ps -a 二.创建交互式容器 命令: docker run -i -t ubuntu /bin/bash 其中-i -t 表示创建一个提供交互式shell ...

  6. Mysql zip 安装(windows)

    Mysql Windows zip包安装 Mysql 下载地址: http://dev.mysql.com/downloads/mysql/ 下载windows 版本对应的zip,之后解压 在C:\P ...

  7. CentOS 6.4 + 曙光DS200 IPSan组建FTP服务器

    CentOS 6.4 + 曙光DS200 IPSan组建FTP服务器 http://write.blog.csdn.net/postedit/10911105#本系列文章由ex_net(张建波)编写, ...

  8. Hauntbox:用于控制你的自己主动化、电子创意家居的开源硬件盒子

    Hauntbox 是一个开源硬件控制器,能够满足用随意传感器和控制器建立复杂的.自己主动化的萦绕在心头的电子项目. 它不须要焊接或者预先学什么知识.是全然可控制.并与Arduino插板兼容. 无需编程 ...

  9. CentOS下利用sshpass不用手动输入密码远程执行命令

       在测试的时候要同时操作多台机器,每次都要挨个去执行几乎相同的命令或者修改一些设置,这样很影响工作效率也很烦,所以就想写一个脚本,远程自动去做这些操作.远程执行命令很简单,但是不能在执行命令加上命 ...

  10. QUrl不同版本之间的坑

    在项目中使用了native application + html的方式构建界面. 之前在4.8.4用QUrl直接加载相对路径一点问题都没有.但是切换到5.1编译之后却发现本地的html文件全部没有加载 ...