【发布时间】:2016-06-30 09:23:27
【问题描述】:
我在子对话框中创建了一个 CStatic 控件,效果很好。问题是关闭子对话框后内存没有正确释放。
我试图覆盖PostNCDestoy,就像这个线程中描述的那样:
Is this a memory leak in MFC
但这通过调用“删除这个”给了我一个未处理的异常。
知道释放 CStatic、CButtons 以避免内存泄漏的正确方法是什么吗?
CChildDlg.h
class CChildDlg
{
std::vector<CStatic*> m_images;
void addNewImage(const int &xPos, const int &yPos)
...
}
CChildDlg.cpp
void CChildDlg::addNewImage(const int &xPos, const int &yPos){
CImage imgFromFile;
CStatic *img = new CStatic;
imgFromFile.Load(_T("someImg.jpg"));
int width = imgFromFile.GetWidth();
int height = imgFromFile.GetHeight();
img->Create(_T("Image"), WS_CHILD | WS_VISIBLE | SS_BITMAP,
CRect(xPos, yPos, xPos + width, yPos + height), this, 10910);
HBITMAP hbmOld = img->SetBitmap(imgFromFile.Detach());
if (hbmOld != nullptr){
::DeleteObject(hbmOld);
}
m_images.pushback(img);
}
根据此线程中的建议,我更改了如下代码:
CChildDlg.h
class CChildDlg
{
private:
typedef std::vector<std::unique_ptr <CStatic>> CStaticImgs;
CStaticImgs m_images;
void addNewImage(const int &xPos, const int &yPos)
...
}
CChildDlg.cpp
void CChildDlg::addNewImage(const int &xPos, const int &yPos){
CImage imgFromFile;
std::unique_ptr<CStatic> img(new CStatic);
imgFromFile.Load(_T("someImg.jpg"));
int width = imgFromFile.GetWidth();
int height = imgFromFile.GetHeight();
img->Create(_T("Image"), WS_CHILD | WS_VISIBLE | SS_BITMAP,
CRect(xPos, yPos, xPos + width, yPos + height), this, 10910);
HBITMAP hbmOld = img->SetBitmap(imgFromFile.Detach());
if (hbmOld != nullptr){
::DeleteObject(hbmOld);
}
m_images.pushback(std::move(img));
}
代码运行良好,但泄漏仍然存在。仅当我删除将位图设置为 CStatic 的行时,泄漏才会消失:
//HBITMAP hbmOld = img->SetBitmap(imgFromFile.Detach());
//if (hbmOld != nullptr){
//::DeleteObject(hbmOld);
//}
因此,它必须与以某种方式将 CImage 的所有权接管给 CStatic 有关。我正在向对话框加载多达 100 张图像。每次打开对话框时,我仍然可以看到内存显着增加,关闭后内存不会下降。
任何其他建议可能会丢失什么?
【问题讨论】:
-
不要动态创建CStatic,作为成员放入CChildDlg。
-
我的 CStatic 对象数量只有在运行时才知道。
-
你确定你有内存泄漏吗?您是否在子窗口的析构函数中进行了调试和设置并且没有命中断点(将任何自定义窗口添加到您的窗口以进行测试)?您引用的答案是关于无模式对话框窗口,而不是主框架的子窗口(发帖人特别将其排除在他的答案之外。)
-
您的容器类应该存储对象本身,而不是指向它们的指针。然后,当容器超出范围时(即,当调用类的析构函数时),它将自动释放它包含的所有
CStatic对象。 -
嗯,好点子。虽然可复制在技术上不是标准容器的要求,但我想这些 MFC 类也不是可移动的。然后使用智能指针。制作
std::unique_ptr对象的向量,一旦向量超出范围,它将通过指针自动删除CStatic对象。 (基本点是,利用SBRM 和现代C++ 习惯用法,而不是手动调用delete。)
标签: c++ visual-c++ mfc