Why does a Process's "Private Bytes" memory counter never return back to it's original value?
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,520KLeak 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,552KNew 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 /*=NU开发者_如何转开发LL*/)
: 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 delete
s 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).
This is not an indication of a memory leak. The OS only counts the 4k-sized pages assigned to your process. The heap allocator running inside your process will request and release OS pages on your behalf. The heap manager may keep memory after you release it, to reuse it later for other objects.
You need to instrument your application to find memory leaks, and/or run long running stress tests to detect accumulating leaks.
精彩评论