C语言中的内存分配与释放

  对C语言一直都是抱着学习的态度,很多都不懂,今天突然被问道C语言的内存分配问题,说了一些自己知道的,但感觉回答的并不完善,所以才有这篇笔记,总结一下C语言中内存分配的主要内容。

相关问题 

  刚刚在一篇博文看到一个简单的问题:

  1. //code1
  2. char* toStr()
  3. {
  4. char *s = "abcdefghijkl";
  5. return s;
  6. }
  7. int main()
  8. {
  9. cout << toStr() << endl;
  10. return ;
  11. }
  12.  
  13. //code2
  14. char* toStr()
  15. {
  16. char s[] = "abcdefghijkl";
  17. return s;
  18. }
  19. int main()
  20. {
  21. cout << toStr() << endl;
  22. return ;
  23. }

  两段代码都很简单,输出一段字符,类型不同,一个是char*字符串,一个是char[]数据。

  结果你知道吗? 这个我确实知道,相信大部分人也都回知道,必然有一个不好使,或者两个都不好使!!!都对就没意思了~

  结果:第一个正确输出,第二个输出乱码。

  原因:在于局部变量的作用域和内存分配的问题,第一char*是指向一个常量,作用域为函数内部,被分配在程序的常量区,直到整个程序结束才被销毁,所以在程序结束前常量还是存在的。而第二个是数组存放的,作用域为函数内部,被分配在栈中,就会在函数调用结束后被释放掉,这时你再调用,肯定就错误了。

内存分配

  什么是局部变量、全局变量和静态变量?

  顾名思义,局部变量就是在一个有限的范围内的变量,作用域是有限的,对于程序来说,在一个函数体内部声明的普通变量都是局部变量,局部变量会在栈上申请空间,函数结束后,申请的空间会自动释放。而全局变量是在函数体外申请的,会被存放在全局(静态区)上,知道程序结束后才会被结束,这样它的作用域就是整个程序。静态变量和全局变量的存储方式相同,在函数体内声明为static就可以使此变量像全局变量一样使用,不用担心函数结束而被释放。

相关函数:

  1. void *malloc(size_t size);
  2. void free(void *p);
  3.  
  4. /*一般这样用
  5. Struct elem *p;
  6. p = (struct elem*)malloc(sizeof(struct elem))
  7.  
  8. void free(p)
  9. */

malloc原理

  malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表。调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。如果无法获得符合要求的内存块,malloc函数会返回NULL指针,因此在调用malloc动态申请内存块时,一定要进行返回值的判断。

分类:

  • 栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
  • 堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表
  • 全局区(静态区)(static)—全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态                                  变量在相邻的另一块区域。  程序结束后由系统释放。
  • 常量区—常量字符串就是放在这里的,直到程序结束后由系统释放。上面的问题就在这里!!!
  • 代码区—存放函数体的二进制代码。

直接搬运的代码,确实很好!!容易理解

  1. //main.cpp
  2. int a = ; //全局初始化区
  3. char *p1; //全局未初始化区
  4.  
  5. main()
  6. {
  7. int b; //栈
  8. char s[] = "abc"; //栈
  9. char *p2; //栈
  10. char *p3 = ""; //123456\\0在常量区,p3在栈上。
  11. static int c =;//全局(静态)初始化区
  12. p1 = (char *)malloc();
  13. p2 = (char *)malloc();//分配得来得10和20字节的区域就在堆区。
  14. strcpy(p1, ""); //123456\\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
  15. }

此外,还有realloc(重新分配内存)、calloc(初始化为0)、alloca(在栈上申请内存,自动释放)等。

C语言中的内存分配与释放的更多相关文章

  1. C语言中动态内存分配的本质是什么?

    摘要:C语言中比较重要的就是指针,它可以用来链表操作,谈到链表,很多时候为此分配内存采用动态分配而不是静态分配. 本文分享自华为云社区<[云驻共创]C语言中动态内存分配的本质>,作者: G ...

  2. [c语言]c语言中的内存分配[转]

    在任何程序设计环境及语言中,内存管理都十分重要.在目前的计算机系统或嵌入式系统中,内存资源仍然是有限的.因此在程序设计中,有效地管理内存资源是程序员首先考虑的问题. 第1节主要介绍内存管理基本概念,重 ...

  3. c语言中的内存分配malloc、alloca、calloc、malloc、free、realloc、sbr

    C语言跟内存分配方式 (1) 从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. (2) 在栈上创建.在执行函数时,函数内局部变 ...

  4. C语言中的内存分配

    对于一个C语言程序而言,内存空间主要由以下几个部分组成: 1)程序代码区:用来存储程序的二进制代码 2)全局区/静态存储区 3)BSS段:用来存储未初始化的全局变量和静态变量. 4)栈区:存储局部变量 ...

  5. DLL函数中内存分配及释放的问题

    DLL函数中内存分配及释放的问题 最近一直在写DLL,遇到了一些比较难缠的问题,不过目前基本都解决了.主要是一些内存分配引起问题,既有大家经常遇到的现象也有特殊的 情况,这里总结一下,做为资料. 错误 ...

  6. (转)C++ STL中的vector的内存分配与释放

    C++ STL中的vector的内存分配与释放http://www.cnblogs.com/biyeymyhjob/archive/2012/09/12/2674004.html 1.vector的内 ...

  7. Com组件的内存分配和释放,CredentialProvider SHStrDup 字符串拷贝问题

    一.简单介绍 熟悉CredentialProvider的同学应该知道,他为一个Com组件,于是,在这里的内存分配(字符串拷贝)的一系列操作就要依照con的标准来. 二.Com组件的内存分配和释放 CO ...

  8. C语言中的内存管理

    开始陆续的发一下唐老师视频的笔记吧,顺便带一些正冲哥书的的内容.不能一下都发出来,因为内容发多了自己也受不了,而且发的都是学习视频时候的一些笔记,可能会有一些问题不是很清晰. 先说一下C语言中的内存管 ...

  9. C语言数据在内存分配

    一个由C/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)— 程序运行时由编译器自动分配,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈.程序结束时由编译器自动释放 ...

随机推荐

  1. poj3241 曼哈顿最小距离生成树第k大的边

    思路: 已知: 要生成曼哈顿距离最小生成树,一个点最多和四周8个点连线,那8个点分别是将那个点四周360度平分成8个区间,每个区间里面和那个点曼哈顿距离最小的点,所以如果有n个点,那么最多有4n条边, ...

  2. C语言-------多文件编译

    (1)前段时间,学长讲解宏的一些知识  也提起了那个多文件编译,同过看别人的博客,自己也懂了一些,现在来总结一下这个多文件编译,其实和java里面的那个class的调用好像有联系 其定义即可以理解成: ...

  3. source : not found 原因及解决办法

    解决方案来自网络: debian中shell脚本无法使用source的原因及解决方法 现象: shell脚本中source aaa.sh时提示 source: not found 原因: ls -l ...

  4. protobuff 配合 libevent 在Linux 和windows 下的使用

    protobuff 配合 libevent 在Linux 和windows 下的使用待补全. libprotobuf.lib libproto-lite.lib libprotoc.lib

  5. MySQL安装常见问题(找不到文件,系统服务无法启动...)

    在安装mysql时总是会遇到问题,每次重新安装都会花很多时间来排查.在网上其实有很多相关的文章,但很多都只讲了方法,但没讲具体细节问题,导致无法解决问题.其实有时候知道问题的原因,但总是因为一些细节问 ...

  6. 用AXIS2发布WebService的方法

    Axis2+tomcat6.0 实现webService 服务端发布与客户端的调用. 第一步:首先要下载开发所需要的jar包 下载:axis2-1.6.1-war.zip http://www.apa ...

  7. linux中的开机和关机命令

    与关机.重新启动相关的命令 * 将数据同步写入硬盘中的命令  sync * 惯用的关机命令  shutdown * 重新启动.关机  reboot halt poweroff sync 强制将内存中的 ...

  8. 对CLR基本原理概念&垃圾回收机制的简单理解

    前言,之前有说过C语言的函数&变量的一些基本概念,说得可能不是很好,先也把C#的.里相关的也说下,已成一统. 而说函数变量,其实主要就是GC,而GC又是CLR的主要内容,故就有了此文. CLR ...

  9. Oracle常量

    Oracle是有常量的,而SqlServer是没有常量的 queryFrom constant ) := ' hello ';

  10. 用nodej和glub-watcher写的监听go 项目自动编译,很鸡肋

    glub 一般都是很轻量的编译. go太重了,改一小个部分,就编译的话,多数是编译失败. 而且很消耗性能,还没想到完美的优化办法. 暂时用个定时器 监听2秒,停止1秒,如此循环,会减少些 “无效”的编 ...