zoukankan      html  css  js  c++  java
  • 一定要弄懂GetMemory

    堆栈

    中分配局部变量空间,是系统自动分配空间。定义一个 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在常量区,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.     
    6. void Test1(void)    
    7. {    
    8.     char *str = NULL;    
    9.     GetMemory1(str);      
    10.     strcpy(str, "hello world");    
    11.     printf(str);  //str一直是空,程序崩溃     
    12. }    
    结果:

    分析:

            毛病出在函数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.     
    6. void Test2(void)    
    7. {    
    8.     char *str = NULL;    
    9.     GetMemory2(&str, 100);    
    10.     strcpy(str, "hello");      
    11.     printf(str);        
    12. }    

    结果:输出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.      
    7. void Test4(void)    
    8. {    
    9.     char *str = NULL;    
    10.     str = GetMemory4();   
    11.     cout<< str << endl;    
    12. }    
    结果:输出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.   
    12. void main(){    
    13.     GetMemory6();  
    14. }    
    结果:能够输出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
  • 相关阅读:
    大数据分析谨慎对待
    大数据时代下,市场研究何去何从
    大数据时代下,市场研究何去何从
    浅谈数据挖掘与数据分析?
    浅谈数据挖掘与数据分析?
    大数据的七种商业化模式
    大数据的七种商业化模式
    栈的应用---编译器左右符号的语法匹配
    Python 对Twitter tweet的元素 (Word, Screen Name, Hash Tag)的频率分析
    东华软件笔试
  • 原文地址:https://www.cnblogs.com/Zoran-/p/5819202.html
Copyright © 2011-2022 走看看