为了账号安全,请及时绑定邮箱和手机立即绑定

申请内存问题

#include <string.h>
#include <iostream>
using namespace std;
int main(void)
{
    //在堆中申请100个char类型的内存
    char *str = new char[6];
    //拷贝Hello C++字符串到分配的堆中的内存中
    strcpy(str, "Hello imooc");
    //打印字符串
    cout << str << endl;
    //释放内存
    delete []str;
    str =NULL;
    return 0;
}

//申请的内存小于Hello imooc,为什么也成功。

正在回答

3 回答

学习了啊!!牛!

0 回复 有任何疑惑可以回复我~

回答很有用!

0 回复 有任何疑惑可以回复我~

    尽管楼主的代码可以得到正确输出,但实际上发生了‘缓冲溢出’的错误。之所以楼主得到正确输出应该是视频作者提供的编译器存在Bug没有报错导致的。排名第一的答案在VS2015中编译也会报错。

    错误的根源在于strcpy函数。strcmp函数在运行时的过程如下:首先生成一个缓冲区buffer,缓冲区没有限制大小可以接收任意长的字符串(本例为"Hello imooc")。然互缓冲区中的字符串拷贝到str,str在内存中指向char型数组(大小为6字节),也就是说"Hello imooc"拷贝到了char型数组中。尽管数组大小为6不够存放"Hello imooc"字符串,"Hello imooc"中的超出的部分会继续存在char型数组之后的内存地址中。

    那么当执行cout << str << endl时,会完整的输出"Hello imooc"字符串。因为字符串在内存中存放时是以‘\0’结束,cout函数输出str时,遇到‘\0’才会结束输出。而‘\0’并没有在大小为6字节的char数组(指针str指向数组起始地址)里面,而是在char数组之后的内存地址中,所以cout读取完数组之后并不会停止,还会继续读取内存中数组之后的字符串直到遇到‘\0’才结束输出。

    另外排名第一的答案在VS2015中编译也会报错,也是由于strcmp函数。因为strcmp函数执行时产生的缓冲区buffer没有指定大小,很可能发生‘缓冲溢出’的风险。这其实是strcmp这个函数自身的Bug。解决办法是换成strcmp函数改为strcmp_s函数,strcmp_s函数中的第二个参数会指定缓冲区buffer的大小,从而避免了‘缓冲溢出’的错误。

    正确的代码应该如下(VS2015环境亲测),注意下面加粗倾斜字体:

#include <string.h>

#include <iostream>

using namespace std;

int main(void)

{

//在堆中申请100个char类型的内存

char *str = new char[20];

//拷贝Hello C++字符串到分配的堆中的内存中

strcpy_s(str,15, "Hello imooc");

//打印字符串

cout << str << endl;

//释放内存

delete []str;

str = NULL;

system("pause");

return 0;

}

另外附上一片博客供楼主参考:http://blog.csdn.net/wiscada/article/details/3123812。

我是根据这篇文字才知道的答案。


3 回复 有任何疑惑可以回复我~
#1

慕粉3631940

说的不错,笑纳!
2016-07-13 回复 有任何疑惑可以回复我~

举报

0/150
提交
取消
C++远征之离港篇
  • 参与学习       122700    人
  • 解答问题       474    个

C++扫清通往面向对象的最后一道障碍,将所有知识点融会贯通

进入课程

申请内存问题

我要回答 关注问题
意见反馈 帮助中心 APP下载
官方微信