堆栈

栈中分配局部变量空间,是系统自动分配空间。定义一个 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. AcWing 105. 七夕祭

    七夕节因牛郎织女的传说而被扣上了「情人节」的帽子. 于是TYVJ今年举办了一次线下七夕祭. Vani同学今年成功邀请到了cl同学陪他来共度七夕,于是他们决定去TYVJ七夕祭游玩. TYVJ七夕祭和11 ...

  2. AcWing 90. 64位整数乘法

    求a*b%p的值. 0<a,b,p<1e18; 原题链接 #include<bits/stdc++.h> #define ull unsigned long long usin ...

  3. 22 shell组命令与子进程

    1.组命令 2.子进程 2.1 什么是子进程 2.2 创建子进程 2.3 子进程总结 3.如何检测子shell与子进程 1.组命令 组命令,就是将多个命令划分为一组,或者看成一个整体. 用法 区别 S ...

  4. 【Git】pull遇到错误:error: Your local changes to the following files would be overwritten by merge:

    这种情况下,如何保留本地的修改同时又把远程的合并过来呢? 首先取决于你是否想要保存本地修改.(是 /否) 是 git stash git pull origin master git stash po ...

  5. C语言:最大公约数

    //求最大公约数 #include <stdio.h> main() { int m,n,i,k; scanf("%d,%d",&m,&n); k=m& ...

  6. win10 IIS web.config加密不能访问:打不开 RSA 密钥容器

    C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys 找到密钥文件, 根据时间判断具体是哪一个文件,赋予network service读权限

  7. [刘阳Java]_步步窥探JS变量作用域

    今天的这个文章题目名称甚是让人会突发异想.JS变量作用域是务必需要搞懂的,单从面试过程就会让面试者烧脑壳.所以,我们还是写一篇关于JS变量作用域的技术专题,让所有小伙伴能够借此文章去整理JS的基础学习 ...

  8. SLAM基础算法(1):卡尔曼滤波

    对于一个正在运动中的小车来说,如何准确的知道它所处的位置? 理论家说:我可以通过牛顿公式来计算! 实践家说:给它装个GPS不就得了! 好吧,你们说的听上去都很有道理,但我们到底该相信谁? 现实情况是: ...

  9. JDK的环境变量配置(详细步骤)

    JDK环境变量配置的步骤(Windows10) 一.下载并安装JDK 选择一个JDK版本下载并安装到电脑上. 二.环境变量的配置 1.安装完成JDK后的配置环境变量: 首先鼠标右击"计算机& ...

  10. 最小覆盖问题-POJ3041-P1129

    POJ3041 这道题正解对于像我这种蒟蒻来说比较难以想到. 我们发现每次覆盖的只是一条线上的所有点.那么我们可以把它想象成一个二分图,两个集合分别是横轴和纵轴. 想一想,这实际上是不是就是x轴轴和纵 ...