c語言內存對其和內存碎片問題


cpu使用stm32f107,編譯用keil,網絡應用,要求在網絡不通的時候儲存有效數據,到一定程度循環存放,釋放最老的數據包……
當初考慮過使用數組解決,但是因為每包數據長度不固定,使用數組也不是一個很好的辦法;而且儲存的數據多的時候使用數組處理起來更麻煩;使用此種方法是否會造成內存碎片及內存耗盡的情況?
struct LNODE
{

  u16 buflen;          //包長度
  u8  ref;                  //包標志,為1說明該包需要發送
  struct LNODE *next;         //下包地址
  u8 *payload;        //該包未發送數據指針
}
*not_sent_bufs; 
//緩存鏈表首地址

鏈表節點如上,payload為不定長數據包指針,其長度為buflen,為了避免內存碎片,想創建節點時把payload數據內存一並申請,即malloc(sizeof(struct LNODE)+buflen);同時payload指向數據區頭部;可否如此
not_sent_bufs = malloc(sizeof(struct LNODE)+buflen);
not_sent_bufs ->payload = (unsigned char *)not_sent_bufs +sizeof(struct LNODE);  //
memcpy(not_sent_bufs ->payload,sbuf,buflen); //拷貝數據
……
加入節點到鏈表
……

73 个解决方案

#1


比較麻煩,。。

#2


如果內存不大的話,盡量不要用 malloc

#3


嵌入式應用開發,建議只在程序初始化的時候調用malloc申請內存,運行的時候最好不要用。就算申請內存以后正確操作釋放內存,還是可能生成內存碎片。

#4


可以自己在初始化時用malloc申請一片大內存,之后自己實現在那片內存中的分配與釋放。根據你包大小的統計信息自己設計分配算法應該會使內存利用率達到最優

#5


該回復於2012-07-18 13:51:35被版主刪除

#6


比較麻煩,。。 學習了 

#7


到一定程度循環存放,釋放最老的數據包。
一定程度是什么意思?根據緩沖大小來還是根據緩沖時間來?

#8


該回復於2012-07-18 14:44:22被版主刪除

#9


不要動態分配,用內存池。既然是網絡通信,受其協議要求,是有最大值的。
寧肯利用率低一些,不要產生不可控的情況。

#10


循環釋放做一個環形鏈表就行了

#11


內存二次分配。。。
封裝自己的內存申請,釋放接口
先申請一個大塊內存。
再通過自己的接口進行處理。

不過這種方法只適合每次申請得內存比較固定的情況下。

#12


該回復於2012-07-18 16:04:47被版主刪除

#13


該回復於2012-07-18 16:04:09被版主刪除

#14


是有點問題哦!! 看看先!聽聽其他大佬的看法!!

#15


該回復於2012-07-19 08:26:09被版主刪除

#16


該回復於2012-07-19 08:29:22被版主刪除

#17


引用 9 樓  的回復:
不要動態分配,用內存池。既然是網絡通信,受其協議要求,是有最大值的。
寧肯利用率低一些,不要產生不可控的情況。


malloc 就是要產生碎片 

#18


from: http://coolshell.cn/articles/7490.html

內存分配。不要小看程序的內存分配。malloc/realloc/calloc這樣的系統調非常耗時,尤其是當內存出現碎片的時候。我以前的公司出過這樣一個問題——在用戶的站點上,我們的程序有一天不響應了,用GDB跟進去一看,系統hang在了malloc操作上,20秒都沒有返回,重啟一些系統就好了。這就是內存碎片的問題。這就是為什么很多人抱怨STL有嚴重的內存碎片的問題,因為太多的小內存的分配釋放了。有很多人會以為用內存池可以解決這個問題,但是實際上他們只是重新發明了Runtime-C或操作系統的內存管理機制,完全於事無補。當然解決內存碎片的問題還是通過內存池,具體來說是一系列不同尺寸的內存池(這個留給大家自己去思考)。當然,少進行動態內存分配是最好的。說到內存池就需要說一下池化技術。比如線程池,連接池等。池化技術對於一些短作業來說(如http服務)相當相當的有效。這項技術可以減少鏈接建立,線程創建的開銷,從而提高性能。

#19


該回復於2012-07-19 11:46:12被版主刪除

#20


各種不明白,不明白摟主說什么,不明白為什么動態分配,不明白摟主的包為什么不發出去,不明白摟主怎么會產生內存泄露,總之各種不明白,內存泄露了直接free,發不出去就循環測試網絡條件設置標志位,可以發出去的時候就申請空間,申請了就free,然后就OK了,沒法出去的包用自動內存存放

#21


產生內存碎片是難免的,這涉及到windows內部內存管理的問題

#22


該回復於2012-07-19 15:26:02被版主刪除

#23


可以用slab算法管理一下,緩解片外的內存碎片。

也可以參考TCP/IP的buffer管理算法,每次分配的buffer都是固定長度,buffer由head和data組成,head記錄一些信息,data存儲數據,每個node包含若干個buffer,這樣也是可以緩解片外碎片。

#24


C語言直接操作內在,C語言還是很見功底的!

#25


不懂哎

#26


該回復於2012-07-20 08:29:19被版主刪除

#27


恩,內存碎片是難免的,頂

#28


各種不明白,不明白摟主說什么,不明白為什么動態分配,不明白摟主的包為什么不發出去,不明白摟主怎么會產生內存泄露,總之各種不明白

#29


內存碎片是難免的,適當的對調分配內存,可減少內存碎片!

#30


該回復於2012-07-20 10:22:15被版主刪除

#31


該回復於2012-07-20 09:39:04被版主刪除

#32


比較麻煩,。。 學習了

#33


如果想避免在你的系統上碎片太多,申請開銷延遲等問題,一開始就申請一段足夠內存,自己再管理這段內存供你的模塊使用。
自己管理這段內存,肯定也存在釋放分配碎片的問題,不過可以根據你的情況使情況簡化。
如果覺得還是麻煩,就申請固定長度的連續buffer,管理肯定簡單,但缺點是可能浪費內存。。。

根據自己的情況選擇合適的方法。。。

#34


好吧,給你點實用的。
原理很簡單,無非是內存池,slab。
防止內存碎片和反復malloc/free的輕量實現:
http://www.codeproject.com/useritems/Small_Block_Allocator.asp

據我所知,著名的物理引擎box2d也是用這個來進行內存的高效管理的。

#35


該回復於2012-07-20 15:28:27被版主刪除

#36


盡量不要用 malloc

#37


該回復於2012-07-21 10:13:52被版主刪除

#38


該回復於2012-07-21 09:36:47被版主刪除

#39


該回復於2012-07-21 10:13:58被版主刪除

#40


受教了 多謝樓主

#41


該回復於2012-07-22 13:55:00被版主刪除

#42


感謝分享!~

#43


不錯,兩個參考鏈接都挺好的

#44


可以申請大的內存 自己進行管理
可以看看wrk中執行層內存分配的方法,還是很有啟發的

#45


盡量不要用 malloc

#46


引用 28 樓  的回復:
各種不明白,不明白摟主說什么,不明白為什么動態分配,不明白摟主的包為什么不發出去,不明白摟主怎么會產生內存泄露,總之各種不明白

我也是。。。

#47


引用 46 樓  的回復:
引用 28 樓  的回復:

各種不明白,不明白摟主說什么,不明白為什么動態分配,不明白摟主的包為什么不發出去,不明白摟主怎么會產生內存泄露,總之各種不明白

我也是。。。

+1

#48


看看MFC程序編程吧, 里面就有一個簡單的內存池的實現方式, 想要不產生任何內存碎片很簡單的, 只要每次分配的大小都跟頁面大小一至, 這樣就不會有碎片了. 創建出來的大塊數據之后, 再划分成對應大小的每個小塊, 連接起來成為Free鏈表, 申請時只要向Free鏈表查找有沒有可用內存塊, 有就直接返回, 沒有就創建一個新的大塊. 
內存池的方式都基本是這樣子的.

例子里面也是說明了固定長度的內存池, 要做成非固定長度的內存池, 很簡單的, 僅需要加個HASH表, HASH就直接用申請的大小作為KEY即可.
每個HASH都保存着對應的Free鏈表, 那么申請動態內存的時候, 僅需要查找HASH表, 找到對應的FREE鏈表, 為空時, 就創建一個大塊, 並且把划分出來的所有小塊加入當前KEY的Free鏈表即可.

這個就是基礎型的內存池了. 

然后可以加入多一點的統計算法, 或者是直接加入固定的算法, 讓經常使用的內存大小盡量減小釋放所對應的內存塊, 這樣就可以提高不少速度了.

#49


不能忘記 FREE 

#50


可以考慮一下環形隊列

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com