堆栈

栈中分配局部变量空间,是系统自动分配空间。定义一个 char a;系统会自动在栈上为其开辟空间。由于栈上的空间是自动分配自动回收的,所以栈上的数据的生存周期只是在函数的运行过程中,运行后就释放掉,不可以再访问。

堆区分配程序员申请的内存空间,堆上的数据只要程序员不释放空间,就一直可以访问到,不过缺点是一旦忘记释放会造成内存泄露。

静态区是分配静态变量,全局变量空间的。

[cpp] view
plain
 copy

  1. int a = 0; 全局初始化区
  2. char *p1; 全局未初始化区
  3. main(){
  4. int b;      //栈
  5. char s[] = "abc";    //栈
  6. char *p2;      //栈
  7. char *p3 = "123456";   // 123456\0在常量区,p3在栈上。
  8. static int c =0;      //全局(静态)初始化区
  9. p1 = (char *)malloc(10);    //堆  }

GetMemory1

[cpp] view
plain
 copy

  1. void GetMemory1(char *p)
  2. {
  3. p = (char *)malloc(100);
  4. }
  5. void Test1(void)
  6. {
  7. char *str = NULL;
  8. GetMemory1(str);
  9. strcpy(str, "hello world");
  10. printf(str);  //str一直是空,程序崩溃
  11. }

结果:

分析:

毛病出在函数GetMemory1 中。编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是 _p,编译器使 _p = p。如果函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因。在本例中,_p申请了新的内存,只是把 _p所指的内存地址改变了,但是p丝毫未变。所以函数GetMemory并不能输出任何东西。事实上,每执行一次GetMemory1就会泄露一块内存,因为没有用free释放内存。Test1中调用GetMemory1时,函数参数为str的副本不是str本身

GetMemory2

[cpp] view
plain
 copy

  1. void GetMemory2(char **p, int num)
  2. {
  3. *p = (char *)malloc(num);
  4. }
  5. void Test2(void)
  6. {
  7. char *str = NULL;
  8. GetMemory2(&str, 100);
  9. strcpy(str, "hello");
  10. printf(str);
  11. }

结果:输出hello

分析:动态分配的内存不会自动释放;

没有测试是否成功分配了内存,应该有if (*p == NULL) { ……} 之类的语句处理内存分配失败的其情况。

GetMemory3

[cpp] view
plain
 copy

  1. char * GetMemory3(void)
  2. {
  3. char p[] = "hello world";
  4. return p;
  5. }
  6. void Test3(void)
  7. {
  8. char *str = NULL;
  9. str = GetMemory3();
  10. printf(str);
  11. }

结果:输出乱码。

分析:字符数组p存在于栈空间,是局部变量,函数返回后,内存空间被释放,因此输出无效值。字符数组的值是可以修改的,例如p[0] = 't‘。

GetMemory4

[cpp] view
plain
 copy

  1. char *GetMemory4(void)
  2. {
  3. char *p = "hello";
  4. return p;
  5. }
  6. void Test4(void)
  7. {
  8. char *str = NULL;
  9. str = GetMemory4();
  10. cout<< str << endl;
  11. }

结果:输出hello

分析:p指向的是字符串常量,字符串常量保存在只读的数据段,是全局区域,但不是像全局变量那样保存在普通数据段(静态存储区)。无法对p所指的内存的内容修改,例如p[0] = 'y;这样的修改是错误的。


GetMemory5

[cpp] view
plain
 copy

  1. char *GetMemory5(void)
  2. {
  3. return "hello";
  4. }
  5. void Test3(void)
  6. {
  7. char *str = NULL;
  8. str = GetMemory5();
  9. printf(str);
  10. }

结果:输出hello

分析:直接返回常量区。

GetMemory6

[cpp] view
plain
 copy

  1. void GetMemory6(void) {
  2. char *str = (char*)malloc(100);
  3. strcpy(str, "hello");
  4. free(str);
  5. //str = NULL,加上这句程序才不会有野指针
  6. if (str != NULL) {
  7. strcpy(str, "world");
  8. printf(str);
  9. }
  10. }
  11. void main(){
  12. GetMemory6();
  13. }

结果:能够输出world,但程序存在问题。

分析:程序出现了野指针

野指针只会出现在像C和C++这种没有自动内存垃圾回收功能的高级语言中, 所以java或c#肯定不会有野指针的概念. 当我们用malloc为一个指针分配一个空间后, 用完这个指针,把它free掉,但是没有让这个指针指向NULL或某一个特定的空间。如上面程序一样,将str进行free后,只是释放了指针所指的内存,但指针并没有释放掉,此时指针所指的是垃圾内存;这样的话,if语句永为真,if判断无效。delete也存在同样的问题。

      防止产生野指针:(1)指针变量一定要初始化为NULL,因为任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的。(2)当free或delete后,将指针指向NULL。通常判断一个指针是否合法,都是使用if语句测试该指针是否为NULL。

原文:http://blog.csdn.net/u013074465/article/details/42784267

一定要弄懂GetMemory的更多相关文章

  1. 彻底弄懂LSH之simHash算法

    马克·吐温曾经说过,所谓经典小说,就是指很多人希望读过,但很少人真正花时间去读的小说.这种说法同样适用于“经典”的计算机书籍. 最近一直在看LSH,不过由于matlab基础比较差,一直没搞懂.最近看的 ...

  2. 必须弄懂的495个C语言问题

    1.1 我如何决定使用那种整数类型? 如果需要大数 值(大于32, 767 或小于¡32, 767), 使用long 型.否则, 如果空间很重要(如有大数组或很多结构), 使用short 型.除此之外 ...

  3. 打工心态废掉了很多人,包括你吗?(你把现在这家公司的业务都弄清楚、弄懂了吗?君子报仇十年不晚!不离不弃!)good

    我只拿这点钱,凭什么去做那么多工作,我傻呀. 我为公司干活,公司付我一份报酬,等价交换而已,我不欠谁的. 我只要对得起这份薪水就行了,多一点我都不干,做了也白做. 工作嘛,又不是为自己干,说得过去就行 ...

  4. SQL Server-聚焦NOLOCK、UPDLOCK、HOLDLOCK、READPAST你弄懂多少?(三十四)

    前言 时间流逝比较快,博主也在快马加鞭学习SQL Server,下班回来再晚也不忘记更新下博客,时间挤挤总会有的,现在的努力求的是未来所谓的安稳,每学一门为的是深度而不是广度,求的是知识自成体系而不是 ...

  5. 彻底弄懂AngularJS中的transclusion

    点击查看AngularJS系列目录 彻底弄懂AngularJS中的transclusion AngularJS中指令的重要性是不言而喻的,指令让我们可以创建自己的HTML标记,它将自定义元素变成了一个 ...

  6. 彻底弄懂 JavaScript 执行机制

    本文的目的就是要保证你彻底弄懂javascript的执行机制,如果读完本文还不懂,可以揍我. 不论你是javascript新手还是老鸟,不论是面试求职,还是日常开发工作,我们经常会遇到这样的情况:给定 ...

  7. 彻底弄懂 Unicode 编码

    彻底弄懂 Unicode 编码 今天,在学习 Node.js 中的 Buffer 对象时,注意到它的 alloc 和 from 方法会默认用 UTF-8 编码,在数组中每位对应 1 字节的十六进制数. ...

  8. 30分钟彻底弄懂flex布局

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由elson发表于云+社区专栏 目前在不考虑IE以及低端安卓机(4.3-)的兼容下,已经可以放心使用flex进行布局了.什么是flex布 ...

  9. Golang, 以 9 个简短代码片段,弄懂 defer 的使用特点

    作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...

随机推荐

  1. Docker与k8s的恩怨情仇(四)-云原生时代的闭源落幕

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 在本系列前几篇文章中,我们介绍了从Cloud Foundry到Docker等PaaS平台的发展迭代过程.今天 ...

  2. Docker中容器的备份和恢复(可迁移)

    官方文档 备份容器 - save 查看镜像$ docker images 容器快照 - commit$ docker commit CONTAINER xxx/exampleimage-backup: ...

  3. Sentinel流控与熔断

    参考: https://thinkwon.blog.csdn.net/article/details/103770879 项目结构 com.guo     ├── guo-sentinel       ...

  4. 容器化-Docker-1-速查手册-Docker常用命令

    目录 备注 常用命令 Docker镜像管理(操作对象是镜像) Docker容器管理(操作对象是容器) 容器外挂目录(宿主目录映射到容器中) 这篇文章的目的就是把最常用的命令列出来,没时间看速查命令使用 ...

  5. ARTS第六周

    第六周.后期补完,太忙了. 1.Algorithm:每周至少做一个 leetcode 的算法题2.Review:阅读并点评至少一篇英文技术文章3.Tip:学习至少一个技术技巧4.Share:分享一篇有 ...

  6. [刘阳Java]_CSS图片画廊

    图片画廊也是一种比较经典的案例.本节文章主要简单给大家介绍了CSS2实现图片画廊,采取的实现思路 ul放置图片 li标签里面嵌套a标签 a标签里面嵌套两个图片的标签 通过简单的伪类来实现图片预览效果 ...

  7. SpringBoot总结之属性配置

    一.SpringBoot简介 SpringBoot是spring团队提供的全新框架,主要目的是抛弃传统Spring应用繁琐的配置,该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配 ...

  8. 【Azure 应用服务】App Service服务无法启动,打开Kudu站点,App Service Editor 页面均抛出:The service is unavailable

    问题描述 App Service 服务URL无法访问,进入门户中的Advanced Tools(Kudu).App Service Editor (Preview)等页面无法打开, 打开就出现 The ...

  9. jumpserver 用户,系统用户和管理用户 普通用户和特权用户 区别

    前言 现在很多公司都有在用Jumpserver跳板机 有很多人一直对jumpserver的各种用户还不是很了解 当你了解了这几个概念了之后,就能更好的灵活的运用到分配权限当中去. 下面我们一个一个的说 ...

  10. Python自动化测试面试题-Selenium篇

    目录 Python自动化测试面试题-经验篇 Python自动化测试面试题-用例设计篇 Python自动化测试面试题-Linux篇 Python自动化测试面试题-MySQL篇 Python自动化测试面试 ...