zoukankan      html  css  js  c++  java
  • 关于栈空间和堆空间的问题

    操作系统对于内存的两种管理方式

    如鹏网 《C语言也能干大事》http://www.rupeng.com/Courses/Index/12

    第三章透彻讲指针 之  第 15 节: 栈空间 

    平时我们定义的变量都是分布在栈空间里,如下面的程序所示

    1 #include <stdio.h>
    2 int main(int argc, char *argv[])
    3 {
    4     int i=5;
    5     char s[] = "afasdfsfwfw";    
    6     return 0;
    7 }

    栈空间:出了函数范围,内存空间自动释放。定义的局部变量int、局部数组等都在栈空间中。栈空间的尺寸有最大的限制,不适合分配大空间使用;栈空间出了函数范围就释放,不适合要给其他地方使用的内存。好处:不需要手动释放。

     1 #include <stdio.h>
     2  
     3 int *getData()
     4 {
     5     int nums[10]={1,2,3,4,5,6,7,8};
     6     return nums;
     7 }
     8  
     9 int *getData3()
    10 {
    11      int i=5;
    12      return &i;
    13 }
    14  
    15 int *getData2()
    16 {
    17     int aaa[10]={8,7,6,5,4,3,2,1};
    18     return aaa;
    19 }
    20  
    21 int main(int argc, char *argv[])
    22 {
    23     int * nums = getData();
    24     getData2();
    25     printf("%d,%d,%d",nums[0],nums[1],nums[2]);
    26     return 0;
    27 }

    上面程序第24行,如果注释getData2(),上述程序的执行结果是1,2,3

    但是如果不注释getData2(),上述程序的执行结果是:8,7,6

    这里很好的反映了栈空间的问题,因为注释getData2()时,函数getData1()申请了栈空间存储数组{1,2,3,4,5,6,7,8},指针num指向该数组首地址,所以打印输出结果为1,2,3;但是一旦加入getData2(),因为getData1()执行完毕退出了,它申请的内存空间(存储数组的)就被释放掉了,再执行getData2(),该函数同样申请内存空间{8,7,6,5,4,3,2,1}覆盖了前述的数组{1,2,3,4,5,6,7,8}占用内存,故输出结果变成了8,7,6。

    注意:因此这里有一个编程规范,不要把局部变量的指针作为函数返回值返回

     第二部分是堆空间的学习内容

    堆空间:手动分配,使用完成之后需要手动释放。使用malloc分配,使用free释放。执行下列代码,会看到程序的内存在暴涨

    要在内存

    优点:可以动态分配内存,分配比较大的内存,比如下载软件每下载10M,才把缓冲区(分配的动态内存)的数据写入磁盘。

    下面是跟前面一样的功能样例,但是使用了动态内存分配,也就是堆空间的方法,最终打印输出结果为1,2,3

     1 #include <stdio.h>
     2 #include <stdlib.h>//malloc在该头文件中声明
     3 int *getData1()
     4 {
     5     int *nums = (int *)malloc(sizeof(int)*3);
     6     nums[0] = 1;
     7     nums[1] = 2;
     8     nums[2] = 3;
     9     return nums;
    10 }
    11 int *getData2()
    12 {
    13     int *nums = (int *)malloc(sizeof(int)*3);
    14     nums[0] = 4;
    15     nums[1] = 5;
    16     nums[2] = 6;
    17     return nums;
    18 }
    19 int main(int argc, char *argv[])
    20 {
    21     int *num1 = getData1();
    22     int *num2 = getData2();
    23      printf("%d,%d,%d
    ",num1[0],num1[1],num1[2]);
    24     free(num1);//由调用者释放内存,如果不释放,会导致内存泄露
    25     free(num2);
    26     return 0;
    27 }

    函数返回指针的方法

    方法1:在方法内malloc,用完了由调用者free

    方法2:把局部变量定义为static,不适合于多线程调用,如果想保存返回内容,你需要调用者尽快复制一份。

    方法3:由调用者分配内存空间,只是把指针发给函数,函数内部把数据拷贝到内存中(推荐)。案例:从文件名分析文件名和扩展名。

     1 #include <stdio.h>
     2 #include <string.h>
     3  
     4 void parseFileName(char* filename,char* name,
     5     char* ext)
     6 {
     7     char *ptr=filename;
     8  
     9     while(*ptr!='')
    10     {
    11         ptr++;
    12     }
    13     char *endPtr = ptr;//结尾的指针
    14     //ptr移动到了字符串的结尾
    15     //再把ptr移动到"."的位置
    16     while(*ptr!='.')
    17     {
    18         ptr--;
    19     }
    20     memcpy(name,filename,(ptr-filename)*sizeof(char));
    21     memcpy(ext,ptr+1,(endPtr-ptr)*sizeof(char));
    22 }
    23  
    24 int main(int argc, char *argv[])
    25 {
    26     char str[]="[TK-300]美.女.avi"; //调用者分配内存空间
    27     char name[20]={0};//调用者分配内存空间
    28     char ext[20]={0};//调用者分配内存空间
    29     parseFileName(str,name,ext);
    30     printf("文件名:%s,后缀:%s",name,ext);
    31     return 0;
    32 }

     补充:memset()与memcpy()的功能?

        strcpy()与strcpy_s()的差别?

  • 相关阅读:
    Android拍照+方形剪裁——附代码与效果图
    Caffe源代码中Solver文件分析
    Java学习笔记五(多线程)
    setTimeout和setInterval的区别
    javascript中this的妙用
    javascript基于原型的语言的特点
    css样式小技巧
    html块元素和内联元素
    怎么解决浏览器兼容性问题
    高效率、简洁、CSS代码优化原则
  • 原文地址:https://www.cnblogs.com/codecamel/p/4590424.html
Copyright © 2011-2022 走看看