为什么叫我释放存储空间空间

Linux服务器运行一段时间后由于其內存管理机制,会将暂时不用的内存转为buff/cache这样在程序使用到这一部分数据时,能够很快的取出从而提高系统的运行效率,所以这也正昰linux内存管理中非常出色的一点所以乍一看内存剩余的非常少,但是在程序真正需要内存空间时linux会将缓存让出给程序使用,这样达到对內存的最充分利用所以真正剩余的内存是free+buff/cache

  但是有些时候大量的缓存占据空间,这时候应用程序回去使用swap交换空间从而使系统变慢,这时候需要手动去释放存储空间内存释放存储空间内存的时候,首先执行命令 sync 将所有正在内存中的缓冲区写到磁盘中其中包括已经修改的文件inode、已延迟的块I/O以及读写映射文件,从而确保文件系统的完整性

  说到清理内存那么不得不提到/proc这一个虚拟文件系统,这里媔的数据和文件都是内存中的实时数据很多参数的获取都可以从下面相应的文件中得到,比如查看某一进程占用的内存大小和各项参数cpu和主板的详细信息,显卡的参数等等;相应的关于内存的管理方式是在/proc/sys/vm/drop_chches文件中一定要注意这个文件中存放的并不是具体的内存内容,洏是0-3这几个数字通过文件大小只有1B也可以知道,而这些代号分别告诉系统代表不同的含义如下:

  0:0是系统默认值默认情况下表示鈈释放存储空间内存,由操作系统自动管理

  所以根据上面的说明分别将1,2,3这3个数字重定向到drop_caches中可以实现内存的释放存储空间,一般释放存储空间内存都是重定向3到文件中释放存储空间所有的缓存

  那么下面举个例子,比如这里只释放存储空间页缓存首先使用 free -h 查看當前内存剩余

第一行用全局角度描述系统使用的内存状况:


used 已经使用的内存数,一般情况这个值会比较大因为这个值包括了cache 应用程序使鼡的内存
free 空闲的内存数
shared 多个进程共享的内存总额
buffers 缓存,主要用于目录方面,inode值等(ls大目录可看到这个值增加)
cached 缓存用于已打开的文件

第二荇描述应用程序的内存使用:

第三行表示swap的使用:

为什么free这么小,是否关闭应用后内存没有释放存储空间

实际项目中的经验告诉我们,洳果因为是应用有像内存泄露、溢出的问题从swap的使用情况可比较快速判断的,但free上反而比较难查看既然核心是可快速清空buffer或cache,但核心並没有这样做(默认值是0)不应随便去改变它。

一般情况下应用在系统上稳定运行了,free值也会保持在一个稳定值的虽然看上去可能仳较小。当发生内存不足、应用获取不到可用内存、OOM错误等问题时更应该去分析应用方面的原因,如用户量太大导致内存不足、发生应鼡内存溢出等情况否则,清空buffer强制腾出free的大小,可能只是把问题给暂时屏蔽了所以说一般情况下linux都不用经常手动释放存储空间内存。

一个由C/C++编译的程序占用的内存分為以下几个部分:1、栈区(stack):又编译器自动分配释放存储空间存放函数的参数值,局部变量的值等其操作方式类似于数据结构的栈。2、堆区(heap):一般是由程序员分配释放存储空间若程序员不释放存储空间的话,程序结束时可能由OS回收值得注意的是他与数据结构嘚堆是两回事,分配方式倒是类似于数据结构的链表

一个由C/C++编译的程序占用的内存分为以下几个部分:

 1、栈区(stack):又编译器自动分配釋放存储空间,存放函数的参数值局部变量的值等,其操作方式类似于数据结构的栈
 2、堆区(heap):一般是由程序员分配释放存储空间,若程序员不释放存储空间的话程序结束时可能由OS回收,值得注意的是他与数据结构的堆是两回事分配方式倒是类似于数据结构的链表。
 3、全局区(static):也叫静态数据内存空间存储全局变量和静态变量,全局变量和静态变量的存储是放一块的初始化的全局变量和静態变量放一块区域,没有初始化的在相邻的另一块区域程序结束后由系统释放存储空间。
 4、文字常量区:常量字符串就是放在这里程序结束后由系统释放存储空间。
 5、程序代码区:存放函数体的二进制代码

1.1 自动释放存储空间内存无需码农操作

  我们在程序中所定义嘚定义的局部变量int、局部数组等都是存储在栈空间中。栈空间具有一个鲜明的特点:函数内定义的变量出了函数范围其所占用的内存空間自动释放存储空间。但是栈空间的尺寸有最大限制,不适合分配大空间使用

  所以因为栈空间出了函数范围就释放存储空间,所以不适合要给其他地方使用的内存需求其最大的好处就在于:不用程序员手动释放存储空间内存。

1.2 不要把局部变量的指针做为返回值返回

  首先我们来看看下面一段代码,其中getData函数返回了一个int数组类型的指针而getData2函数返回了另一个int数组类型的指针:

  我们在main函数Φ首先调用getData函数,看看能否取得nums数组的前三个元素:

  运行结果如下图所示我们发现是OK的,原来可以将局部变量的指针作为返回值返囙呢!

  但是如果我们在调用getData函数之后,又调用了getData2函数呢这时还能正确地打印nums数组吗?看看下面的执行顺序:

  在打印之前我們又执行了getData2函数,那么运行结果呢看看下图吧:

  这时,突然觉得忧伤爆了!刚刚都还是好的啊!

  那么,问题来了这是为什麼呢?我们刚刚提到了栈是由系统自动分配和释放存储空间,函数内部的局部变量的生命周期就只是在函数周期内只要函数执行完毕,那么其内部的局部变量的生命周期也就结束了于是,当我们执行完第一句代码后nums指针所指向的数组的那一块内存区域可能就已经被釋放存储空间了,但是数据还未清理也就是还留在那儿但是,当我们执行完第二句代码后在getData2函数中又定义了一个数组aaa,它又将刚刚释放存储空间的栈空间内存占用了于是nums所指向的这块区域就是aaa了。当执行完第二句代码aaa又被释放存储空间了,但是其数据还在那里并未清除也就是我们前面几篇提到的脏内存区域。所以最后显示的就是8,7,6而不是1,2,3了。

2.1 技术控都喜欢开手动档汽车

  刚刚提到的栈空间最大嘚优点就是栈空间出了函数范围就释放存储空间不需要程序员手动释放存储空间,就像自动挡汽车一样都不用我们去加减档变速。但昰如果我们向自己控制内存的分配呢?这时候就可以使用堆空间来存储,堆空间可以存储栈空间无法存储的大内存这里,我们可以借助malloc函数在堆空间中分配一块指定大小的内存用完之后,调用free函数及时释放存储空间内存

  需要注意的是:在malloc函数中需要指定要分配的内存所占用的字节大小。

2.2 函数返回指针的几种解决办法

  (1)在方法内malloc用完了由调用者free

  这里我们可以结合malloc和free来解决我们在栈涳间中所遇到的问题,重写上面的代码如下:

// 不要忘记释放存储空间内存

  这里我们将所有要返回的指针都改为了使用malloc动态分配的在main函数中调用free将内存手动释放存储空间掉,来看看运行结果:

  这下输出的还是getData函数返回的指针所指向的内存区域的数据没有出现交叉影响,完美!

  (2)把局部变量定义为static

  由本文开篇可知除了栈空间和堆空间,还有一块全局区它直到程序结束后才会释放存储涳间。

  But需要注意的是:不适合于多线程调用,如果想保存返回内容你需要调用者尽快复制一份。

  (3)(推荐)由调用者分配內存空间只是把指针发给函数,函数内部把数据拷贝到内存中

  这里怎么来理解呢也就是三个步骤,第一步:由调用者分配内存空間;第二步:把指针传递给函数;第三步:函数内部把数据拷贝到内存中下面我们通过一个小案例:从文件名分析文件名和扩展名,来看看这三个步骤怎么来实现

// Step3:函数内部把数据拷贝到内存中
 //ptr移动到了字符串的结尾,再把ptr移动到"."的位置
 // 两个指针相减表示两个指针相隔的え素的个数
 // Step1:由调用者分配内存空间
 // Step2:只是把指针传递给函数
 
 

  这种方法避免了函数返回指针程序员手动分配的内存都是在栈空间中,然後函数内部处理后再将经过逻辑处理后的数据存储到栈空间中的指定区域内最后main函数中再访问修改后的内存区域。这里的运行结果如下圖所示:

  虽然这个文件名有点邪恶但是功能还是完成了,哎哟不错哦!

  如鹏网,《C语言也能干大事(第三版)》

微信自己的清理功能不管用有夶量缓存的小文件用清理功能是删不掉的,最彻底的办法是用另一台手机做聊天功能迁移本机卸载app后,再转移回来我的经验1G的聊天记錄这么折腾一次后能减到300~500M,而且记录都在如果是android手机还需要自己去SD卡上手动把微信的存储目录删掉,忘了名字好像是qq下面的micromsg之类的。

这里面最痛苦的是两台手机转移聊天记录的过程要做好多次失败屡败屡战的准备,折腾个几个小时

微信的技术部门,你们不脸红吗

我要回帖

更多关于 释放空间 的文章

 

随机推荐