为什么进程的“私有字节”内存计数器永远不会返回到其原始值?

2023-12-19

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

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

如果我查看进程的专用字节计数器,我会得到以下 3 个值:
.
描述......................私有字节数
===================================
应用程序已启动......................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++,因此您可以使用_heapwalk在你做了你的之后delete查看仍在进程堆中的空闲块。如果您确实愿意,也可以致电_heapmin将(至少大部分)可用内存释放回操作系统。早在那时(MS VC++ 4.0,如果没记错的话),MS 有一个直接使用操作系统内存管理的标准库版本,但性能很差(说得好听一点),所以这种情况并没有持续很长时间。

其次,MFC 在后台进行了相当多的操作,它分配各种“东西”以使事情正常工作,但之后不会立即释放它们(并且由于其中大部分或多或少是不可见的,因此没有简单/直接的方法供您释放它)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么进程的“私有字节”内存计数器永远不会返回到其原始值? 的相关文章