为何要处理进程的“专用字节"内存计数器永远不会返回到其原始值? [英] Why does a Process's "Private Bytes" memory counter never return back to it's original value?

查看:125
本文介绍了为何要处理进程的“专用字节"内存计数器永远不会返回到其原始值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有一个本机C ++程序并查看它的初始私人字节"内存计数器,为什么在创建并删除一个对象后它不回到原始值?

例如,如果我有一个带有两个按钮的应用程序(32位,本机C ++ MFC). 一个循环分配一个对象的1,000,000实例,另一个循环分配另一个对象,然后删除这些相同的对象.

如果我查看进程的专用字节计数器,则会得到以下3个值:
.
说明..........专用字节数
==================================
App已启动........ 1,608K
对象.已创建........ 33,176K
对象.已删除..... 2,520K

泄漏912K(2520-1608)吗?

假设我的代码没有泄漏内存,我相信这不是为什么专用字节数不返回到 EXACT 初始值的原因?

如果我再次单击两个按钮(尚未重新启动程序)(第一个按钮创建了另外1,000,000个对象),第二个删除了它们,我将得到以下提示:

对象.已创建........ 33,472K
对象.已删除..... 2,552K

(2552-2520)的新泄漏= 32K

我只是在寻找一种解释,说明为什么记忆不会回到原始值.

样本代码(剥离了一些生成的代码以减少噪声):

class Person
{
public:
   Person(void);
   ~Person(void);

   Person* Next;
   int A;
   int B;
   int C;
   int D;

};


class Cdelme_MFC2005_MemoryTestDlg : public CDialog
{
// some code stripped out here to simplify reading.

   Person* m_PeopleList_First;
   Person* m_PeopleList_Last;

public:
   afx_msg void OnBnClickedButtonAllocate();
   afx_msg void OnBnClickedButtonFree();
};


Cdelme_MFC2005_MemoryTestDlg::Cdelme_MFC2005_MemoryTestDlg(CWnd* pParent /*=NULL*/)
    : CDialog(Cdelme_MFC2005_MemoryTestDlg::IDD, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

   m_PeopleList_First = NULL;
   m_PeopleList_Last = NULL;

}


void Cdelme_MFC2005_MemoryTestDlg::OnBnClickedButtonAllocate()
{
   if ( m_PeopleList_First == NULL )
   {
      m_PeopleList_First = new  Person();
      m_PeopleList_First->A = 0;
      m_PeopleList_Last = m_PeopleList_First;
   }

   int MAX = 1000000;
   for (int i = 0; i <MAX ; i++)
   {
      Person* p = new Person();
      p->A = i;
      m_PeopleList_Last->Next = p;
      m_PeopleList_Last = p;
   }
}

void Cdelme_MFC2005_MemoryTestDlg::OnBnClickedButtonFree()
{
   Person* p = m_PeopleList_First;
   while ( p != NULL )
   {
      Person* pNext = p->Next;
      delete p;
      p = pNext;
   }
   m_PeopleList_First = NULL;
   m_PeopleList_Last = NULL;
}

解决方案

您在这里遇到了几个问题.首先,当您delete内存时,标准库通常不会 not 将该内存释放回操作系统.它通常保留该内存的所有权,但将其标记为可用于其他分配.由于您显然使用的是MS VC ++,因此在执行delete之后可以使用_heapwalk来查看仍在进程堆中的空闲块.如果确实需要,还可以调用_heapmin将(至少大部分)可用内存释放回操作系统.追溯到(MS VC ++ 4.0,如果有内存的话)MS拥有标准库的版本,该版本直接使用操作系统的内存管理,但是性能不佳(说得很好),因此持续时间不长. >

第二,MFC在后台进行了大量的工作,它分配各种东西"来使事情正常工作,但是之后并没有立即释放它们(而且由于大部分或多或少是不可见的,所以这并不容易) /直接方式来释放它).

If I have a native C++ program and look at it's initial "Private bytes" memory counter why would it not go back down to it's original value after an object has been created and then deleted?

For example if I have an application (32bit, Native C++ MFC ) that has two buttons. One in a loop that allocates 1,000,000 instances of an object and then the other button that other then deletes those same objects.

If I look at my Private bytes counters for the process I have the following 3 values:
.
Description.......... Private Bytes Count
============= ======================
App Started.................1,608K
Objects. created........33,176K
Objects. deleted..........2,520K

Leak of 912K ( 2520-1608 ) ?

Assuming that my code does not leak memory which I believe it is not why does the Private bytes count not go back to the EXACT initial value?

If I click on the two buttons again ( not having restarted the program ) ( 1st button creates another 1,000,000 objects ) and the second deletes them I have this:

Objects. created........33,472K
Objects. deleted..........2,552K

New Leak of ( 2552-2520 ) = 32K

I am just looking for an explanation on why the memory would not go back to the orginal value.

Sample Code ( some generated code stripped out to reduce noise ):

class Person
{
public:
   Person(void);
   ~Person(void);

   Person* Next;
   int A;
   int B;
   int C;
   int D;

};


class Cdelme_MFC2005_MemoryTestDlg : public CDialog
{
// some code stripped out here to simplify reading.

   Person* m_PeopleList_First;
   Person* m_PeopleList_Last;

public:
   afx_msg void OnBnClickedButtonAllocate();
   afx_msg void OnBnClickedButtonFree();
};


Cdelme_MFC2005_MemoryTestDlg::Cdelme_MFC2005_MemoryTestDlg(CWnd* pParent /*=NULL*/)
    : CDialog(Cdelme_MFC2005_MemoryTestDlg::IDD, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

   m_PeopleList_First = NULL;
   m_PeopleList_Last = NULL;

}


void Cdelme_MFC2005_MemoryTestDlg::OnBnClickedButtonAllocate()
{
   if ( m_PeopleList_First == NULL )
   {
      m_PeopleList_First = new  Person();
      m_PeopleList_First->A = 0;
      m_PeopleList_Last = m_PeopleList_First;
   }

   int MAX = 1000000;
   for (int i = 0; i <MAX ; i++)
   {
      Person* p = new Person();
      p->A = i;
      m_PeopleList_Last->Next = p;
      m_PeopleList_Last = p;
   }
}

void Cdelme_MFC2005_MemoryTestDlg::OnBnClickedButtonFree()
{
   Person* p = m_PeopleList_First;
   while ( p != NULL )
   {
      Person* pNext = p->Next;
      delete p;
      p = pNext;
   }
   m_PeopleList_First = NULL;
   m_PeopleList_Last = NULL;
}

解决方案

You have a couple of problems here. First of all, when you delete memory, the standard library normally does not release that memory back to the OS. It normally retains ownership of that memory, but marks it as available for other allocations. Since you're apparently using MS VC++, you could use _heapwalk after you do your deletes to see the free blocks still in the process' heap. If you really want to, you could also call _heapmin to release (at least most of) that free memory back to the OS. Way back when (MS VC++ 4.0, if memory serves) MS had a version of the standard library that used the OS's memory management directly, but performance was dismal (to put it nicely), so that didn't last very long.

Second, MFC has a fair amount going on in the background where it allocates various "stuff" to make things work, but doesn't free them immediately afterwards (and since most of it is more or less invisible, there's no easy/direct way for you to free it either).

这篇关于为何要处理进程的“专用字节"内存计数器永远不会返回到其原始值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆