申请与释放内存的问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Longyu_wlz/article/details/83314367

申请内存空间时,申请比需求更多的空间,传地址时,只传递需要的大小,当需要进行扩展时,再使用预留的空间。注意释放时要整个释放。实际上 malloc 在申请内存时就预留了部分空间用来存储内存描述信息,返回的是与需求大小相同大小的内存起始地址。

在 free 的时候,我们传递给 malloc 返回的地址,free 通过该地址找到此块内存区域的描述信息,通过修改描述信息就能够完成内存的释放。free(NULL) 不执行任何操作,不会造成异常。

多次 free 一个内存区域将会导致未定义的问题。malloc 与 calloc 一般情况下返回一个已经对齐的类型的指针。malloc 与 calloc 最大的区别在于 calloc 会将申请到的内存空间清 0,这意味着我们调用 calloc 将会有额外的性能开销。不过因此带来的安全性完全可以挽回清 0 的性能损耗。如果我们直接调用 malloc ,并且未显式清空申请到的内存区域,直接访问时就可能造成严重的问题,毕竟此处内存区域的初值是不确定的呀!

free 函数并不会释放一块内存,它会将待释放的内存放到空闲内存链表中,供下一次 malloc、calloc、realloc 使用。并且,相邻的内存块还以按照预设算法进行合并,合并为一个更大的内存区域供程序使用。malloc 从堆中申请内存,可以调用 sbrk 来根据需要动态调整堆的大小。

《APUE》中相关的描述如下:

尽管 sbrk 能够扩展或缩减进程占用的内存,大多数版本的 malloc 和 free 从来不会减少内存大小。我们 free 的空间一般不会返回到内核,而是被放到 malloc 管理的内存池中以供下一次内存申请使用。malloc 的大多数实现都会申请比请求大小更多的空间,并且使用额外的内存空间来存储记录信息——如块的大小,下一个申请块的指针等等。因此,在申请到的块的前后进行写操作可能会覆盖在其它块中保存的记录信息。这种问题很难定位,并且可能在一段时间之后才会发生,但它一旦发生就是一个大的灾难。

另一个可能的错误是释放一个已经释放的内存或者释放一个不是通过调用 malloc、realloc、calloc 函数在堆中申请的内存。当一个进程调用了 malloc 却忘记了调用 free 来释放,未释放的内存不能被回收使用,这被称为内存泄露。如果我们不调用 free 来释放不再使用的内存,可使用的内存会越来越少,直到用完所有的空闲空间。

展开阅读全文

IO内存申请释放问题

06-04

大家好,最近写了个小小的测试程序,在测试程序中用到了request_mem_region()与release_mem_region()两个函数申请和释放IO内存。但交叉编译后insmod测试模块后再rmmod,出现错误。开发板为S3C2410,代码如下:rn#include rn#include rn#include rn#include rn#include rnrnint dev_major=200;rnrnMODULE_LICENSE ("Dual BSD/GPL");rnrnstatic struct file_operations dev_fops;rnrnstatic ssize_t dev_init(void)rnrn printk(KERN_ALERT "Hello,device initialing!\n");rn request_mem_region(0xfff00000,10,"chdev");rn register_chrdev(dev_major,"chr_dev",&dev_fops);rn return 0;rnrnrnstatic void dev_exit(void)rnrn printk(KERN_ALERT "Now leaving....\n");rn release_mem_region(0xfff00000,10);rn unregister_chrdev(dev_major,"chr_dev");rnrnrnstatic ssize_t dev_open(struct inode *inode,struct file *filp)rnrn printk(KERN_ALERT "Device opened...\n");rn return 0;rnrnrnstatic ssize_t dev_release(struct inode *inode,struct file *filp)rnrn printk(KERN_ALERT "Device closed...\n");rn return 0;rnrnrnstatic ssize_t dev_write(struct file *filp,char __user *buff,rn size_t count,loff_t *offp)rnrn printk(KERN_ALERT "Device writting!\n");rn return 0;rnrnrnstatic ssize_t dev_read(struct file *filp,char __user *buff,rn size_t count,loff_t *offp)rnrn printk(KERN_ALERT "Device reading!\n");rn return 0;rnrnrnstatic struct file_operations dev_fops = rn owner : THIS_MODULE,rn open : dev_open,rn release : dev_release,rn read : dev_read,rn write : dev_writern;rnrnmodule_init(dev_init);rnmodule_exit(dev_exit);rnrn下面是ARM的出错信息:rn/home # rmmod testrnUnable to handle kernel paging request at virtual address 68104a00rnpgd = c3950000rn[68104a00] *pgd=00000000rnInternal error: Oops: 0 [#1]rnModules linked in: testrnCPU: 0rnPC is at 0x68104a00rnLR is at sys_delete_module+0x240/0x2a4rnpc : [<68104a00>] lr : [] Not taintedrnsp : c3e79f3c ip : 20000013 fp : c3e79fa4rnr10: beb86ed4 r9 : c3e78000 r8 : c0036064rnr7 : 00000000 r6 : c3e78000 r5 : bf000954 r4 : c02188a4rnr3 : 68104a02 r2 : bf000954 r1 : c3e79f51 r0 : 00000000rnFlags: nzcv IRQs on FIQs on Mode SVC_32 Segment userrnControl: C000717F Table: 33950000 DAC: 00000015rnProcess rmmod (pid: 718, stack limit = 0xc3e78194)rnStack: (0xc3e79f3c to 0xc3e7a000)rn9f20: 00000000rn9f40: bf000954 00000880 c3e79f3c 74736574 00000800 beb86ed4 00000000 c3e79fb0rn9f60: 000c3bdc beb86ed4 c3e79f9c c3e79f78 c003d5ac c003d380 c3c0042c ffffffffrn9f80: 00000880 00b86ed4 0009d5e4 beb86ed4 00000002 00000081 00000000 c3e79fa8rn9fa0: c0035ee0 c0066c48 beb86ed4 00000002 00900081 000c3fb4 00000880 00000000rn9fc0: 0009d5e4 beb86ed4 00000002 00000000 00000002 000c3bdc beb86ed4 00000002rn9fe0: beb86ce4 beb86cd8 00051290 401b29f0 60000010 00900081 00000000 00000000rnBacktrace:rn[] (sys_delete_module+0x0/0x2a4) from [] (ret_fast_syscall+0rnx0/0x2c)rnr7 = 00000081 r6 = 00000002 r5 = BEB86ED4 r4 = 0009D5E4rnCode: bad PC value.rnSegmentation faultrn/home #rnrn请问下这个错误是因为什么原因 ?LDD3 上说ARM是可以支持上述函数的,可以申请到指定的IO内存,为什么释放失败?请各位大虾指教指教!! 论坛

关于new的申请释放

10-14

不是说new了一个内存以后在不需要的时候应该释放吗?rn但为什么MFC向导创建的部分找不到释放的部分呢?rn比如下面这段代码.new了好多,没见到一个释放,如果要删除一个不用的按钮,那么我用的是函数删除的,那样不是泄露了吗?rnrn[code=C/C++]void CMainFrame::InitializeRibbon()rnrn BOOL bNameValid;rnrn CString strTemp;rn bNameValid = strTemp.LoadString(IDS_RIBBON_FILE);rn ASSERT(bNameValid);rnrn // 加载面板图像:rn m_PanelImages.SetImageSize(CSize(16, 16));rn m_PanelImages.Load(IDB_BUTTONS);rnrn // 初始主按钮:rn m_MainButton.SetImage(IDB_MAIN);rn m_MainButton.SetText(_T("\nf"));rn m_MainButton.SetToolTipText(strTemp);rnrn m_wndRibbonBar.SetApplicationButton(&m_MainButton, CSize (45, 45));rn CMFCRibbonMainPanel* pMainPanel = m_wndRibbonBar.AddMainCategory(strTemp, IDB_FILESMALL, IDB_FILELARGE);rnrn bNameValid = strTemp.LoadString(IDS_RIBBON_NEW);rn ASSERT(bNameValid);rn pMainPanel->Add(new CMFCRibbonButton(ID_FILE_NEW, strTemp, 0, 0));rn bNameValid = strTemp.LoadString(IDS_RIBBON_OPEN);rn ASSERT(bNameValid);rn pMainPanel->Add(new CMFCRibbonButton(ID_FILE_OPEN, strTemp, 1, 1));rn bNameValid = strTemp.LoadString(IDS_RIBBON_SAVE);rn ASSERT(bNameValid);rn pMainPanel->Add(new CMFCRibbonButton(ID_FILE_SAVE, strTemp, 2, 2));rn bNameValid = strTemp.LoadString(IDS_RIBBON_SAVEAS);rn ASSERT(bNameValid);rn pMainPanel->Add(new CMFCRibbonButton(ID_FILE_SAVE_AS, strTemp, 3, 3));rnrn bNameValid = strTemp.LoadString(IDS_RIBBON_PRINT);rn ASSERT(bNameValid);rn CMFCRibbonButton* pBtnPrint = new CMFCRibbonButton(ID_FILE_PRINT, strTemp, 6, 6);rn pBtnPrint->SetKeys(_T("p"), _T("w"));rn bNameValid = strTemp.LoadString(IDS_RIBBON_PRINT_LABEL);rn ASSERT(bNameValid);rn pBtnPrint->AddSubItem(new CMFCRibbonLabel(strTemp));rn bNameValid = strTemp.LoadString(IDS_RIBBON_PRINT_QUICK);rn ASSERT(bNameValid);rn pBtnPrint->AddSubItem(new CMFCRibbonButton(ID_FILE_PRINT_DIRECT, strTemp, 7, 7, TRUE));rn bNameValid = strTemp.LoadString(IDS_RIBBON_PRINT_PREVIEW);rn ASSERT(bNameValid);rn pBtnPrint->AddSubItem(new CMFCRibbonButton(ID_FILE_PRINT_PREVIEW, strTemp, 8, 8, TRUE));rn bNameValid = strTemp.LoadString(IDS_RIBBON_PRINT_SETUP);rn ASSERT(bNameValid);rn pBtnPrint->AddSubItem(new CMFCRibbonButton(ID_FILE_PRINT_SETUP, strTemp, 11, 11, TRUE));rn pMainPanel->Add(pBtnPrint);rn pMainPanel->Add(new CMFCRibbonSeparator(TRUE));rnrn bNameValid = strTemp.LoadString(IDS_RIBBON_CLOSE);rn ASSERT(bNameValid);rn pMainPanel->Add(new CMFCRibbonButton(ID_FILE_CLOSE, strTemp, 9, 9));rnrn bNameValid = strTemp.LoadString(IDS_RIBBON_RECENT_DOCS);rn ASSERT(bNameValid);rn pMainPanel->AddRecentFilesList(strTemp);rnrn bNameValid = strTemp.LoadString(IDS_RIBBON_EXIT);rn ASSERT(bNameValid);rn pMainPanel->AddToBottom(new CMFCRibbonMainPanelButton(ID_APP_EXIT, strTemp, 15));rnrn //// 为“剪贴板”面板添加“主”类别:rn bNameValid = strTemp.LoadString(IDS_RIBBON_HOME);rn ASSERT(bNameValid);rn CMFCRibbonCategory* pCategoryHome = m_wndRibbonBar.AddCategory(strTemp, IDB_WRITESMALL, IDB_WRITELARGE);rnrn //// 创建“剪贴板”面板:rn //bNameValid = strTemp.LoadString(IDS_RIBBON_CLIPBOARD);rn //ASSERT(bNameValid);rn //CMFCRibbonPanel* pPanelClipboard = pCategoryHome->AddPanel(strTemp, m_PanelImages.ExtractIcon(27));rnrn //bNameValid = strTemp.LoadString(IDS_RIBBON_PASTE);rn //ASSERT(bNameValid);rn //CMFCRibbonButton* pBtnPaste = new CMFCRibbonButton(ID_EDIT_PASTE, strTemp, 0, 0);rn //pPanelClipboard->Add(pBtnPaste);rnrn //bNameValid = strTemp.LoadString(IDS_RIBBON_CUT);rn //ASSERT(bNameValid);rn //pPanelClipboard->Add(new CMFCRibbonButton(ID_EDIT_CUT, strTemp, 1));rn //bNameValid = strTemp.LoadString(IDS_RIBBON_COPY);rn //ASSERT(bNameValid);rn //pPanelClipboard->Add(new CMFCRibbonButton(ID_EDIT_COPY, strTemp, 2));rn //bNameValid = strTemp.LoadString(IDS_RIBBON_SELECTALL);rn //ASSERT(bNameValid);rn //pPanelClipboard->Add(new CMFCRibbonButton(ID_EDIT_SELECT_ALL, strTemp, -1));rnrn // 创建和添加“视图”面板:rn bNameValid = strTemp.LoadString(IDS_RIBBON_VIEW);rn ASSERT(bNameValid);rn CMFCRibbonPanel* pPanelView = pCategoryHome->AddPanel(strTemp, m_PanelImages.ExtractIcon (7));rnrn CMFCRibbonButtonsGroup* pButtonsGroup1 = new CMFCRibbonButtonsGroup;rn pButtonsGroup1->AddButton(new CMFCRibbonButton (ID_VIEW_STATUS_BAR, _T("") ,0));rn pButtonsGroup1->AddButton(new CMFCRibbonButton (ID_VIEW_TEMPLATE, _T("") ,1));rn pButtonsGroup1->AddButton(new CMFCRibbonButton (ID_VIEW_CONTROLS_LIST, _T("") ,2));rn pButtonsGroup1->AddButton(new CMFCRibbonButton (ID_VIEW_CONTROLS_PROPERTY, _T("") ,3));rn pButtonsGroup1->AddButton(new CMFCRibbonButton (ID_VIEW_OUTPUT, _T("") ,4));rn pButtonsGroup1->AddButton(new CMFCRibbonButton (ID_VIEW_RESET, _T(""), 5));rn pPanelView->Add(pButtonsGroup1);rnrn // 创建和添加“操作”面板:rn CMFCRibbonPanel* pPanelOperation = pCategoryHome->AddPanel(_T("操作"), m_PanelImages.ExtractIcon (7));rn pPanelOperation->Add(new CMFCRibbonButton (ID_OPERATION_DISPLAYDATA, _T("显示数据\nf"), -1, 1));rn pPanelOperation->Add(new CMFCRibbonButton (ID_OPERATION_DELETEDATA, _T("删除数据\nd"), -1, 1));rn pPanelOperation->Add (new CMFCRibbonSeparator);rnrn // 将元素添加到选项卡右侧:rn bNameValid = strTemp.LoadString(IDS_RIBBON_STYLE);rn ASSERT(bNameValid);rn CMFCRibbonButton* pVisualStyleButton = new CMFCRibbonButton(-1, strTemp, -1, -1);rnrn pVisualStyleButton->SetMenu(IDR_THEME_MENU, FALSE /* 无默认命令*/, TRUE /* 右对齐*/);rnrn bNameValid = strTemp.LoadString(IDS_RIBBON_STYLE_TIP);rn ASSERT(bNameValid);rn pVisualStyleButton->SetToolTipText(strTemp);rn bNameValid = strTemp.LoadString(IDS_RIBBON_STYLE_DESC);rn ASSERT(bNameValid);rn pVisualStyleButton->SetDescription(strTemp);rn m_wndRibbonBar.AddToTabs(pVisualStyleButton);rnrn //右侧帮助元素rn bNameValid = strTemp.LoadString(IDS_RIBBON_HELP);rn ASSERT(bNameValid);rn CMFCRibbonButton* pOnlineHelpButton = new CMFCRibbonButton(ID_ONLINE_HELP, strTemp, -1, -1);rn m_wndRibbonBar.AddToTabs(pOnlineHelpButton);rnrn ////////////////////////////////////////////////////////////////////////////rn //右侧更新元素rn bNameValid = strTemp.LoadString(IDS_RIBBON_UPDATA);rn ASSERT(bNameValid);rn CMFCRibbonButton* pSoftwareUpButton = new CMFCRibbonButton(ID_DATA_UP, strTemp, -1, -1);rn m_wndRibbonBar.AddToTabs(pSoftwareUpButton);rnrn ////////////////////////////////////////////////////////////////////////////rn //右侧注册元素rn bNameValid = strTemp.LoadString(IDS_RIBBON_KEY);rn ASSERT(bNameValid);rn CMFCRibbonButton* pSoftwareKeyButton = new CMFCRibbonButton(ID_SOFT_KEY, strTemp, -1, -1);rn m_wndRibbonBar.AddToTabs(pSoftwareKeyButton);rnrn // 添加快速访问工具栏命令:rn CList lstQATCmds;rnrn lstQATCmds.AddTail(ID_FILE_NEW);rn lstQATCmds.AddTail(ID_FILE_OPEN);rn lstQATCmds.AddTail(ID_FILE_SAVE);rn lstQATCmds.AddTail(ID_FILE_PRINT_DIRECT);rnrn m_wndRibbonBar.SetQuickAccessCommands(lstQATCmds);rnrn m_wndRibbonBar.AddToTabs(new CMFCRibbonButton(ID_APP_ABOUT, _T("\na"), m_PanelImages.ExtractIcon (0)));rn[/code] 论坛

没有更多推荐了,返回首页