问题描述
我在子对话框中创建一个CStatic控件,它工作正常。问题是,在关闭子对话框后,内存不能正确释放。
I'm creating a a CStatic conrol in a child dialog, which works fine. The problem is that after closing the child dialog the memory is not freed correctly.
我试图覆盖 PostNCDestoy
描述在这个线程:
但是这给我一个未处理的异常通过调用删除这个。
I tried to overwrite PostNCDestoy
like described in the this thread:Is this a memory leak in MFCBut this gives me an unhandled exception by calling "delete this".
任何想法是什么正确的方法是释放CStatic,CButtons避免内存泄漏?
Any idea what the right way is to release CStatic, CButtons to avoid memory leaks?
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);
}
根据这个线程中的建议,我改变了如下代码:
Based on the recommendations in this thread I changed the code like followed:
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的行,泄漏消失:
The code works fine, but the leak is still there. Only if I'm removing the line where I'm setting the Bitmap to the CStatic the leak disappears:
//HBITMAP hbmOld = img->SetBitmap(imgFromFile.Detach());
//if (hbmOld != nullptr){
//::DeleteObject(hbmOld);
//}
因此,它必须与接管CImage到CStatic不知何故。我最多加载100个图像到对话框。每次打开对话框我仍然可以看到一个显着提高的内存,关闭后不会下降。
So, it has to be related to taking over the ownership of the CImage to the CStatic somehow. I'm loading up to 100 images to the dialog. By every opening of the dialog I still can see a significant raise of the memory, which not drops after closing it.
任何其他建议可能错误的错误?
Any other suggestion what might be wrong of missing?
推荐答案
这个简单的解决方案是简单地遍历你的容器类,调用 delete
每个指针。例如:
The naïve solution would be to simply iterate through your container class, calling delete
on each pointer. Something like:
for (auto i : m_images) { delete i; } // on C++11
for (size_t i = 0; i < m_images.size(); ++i) { delete m_images[i]; } // on C++03
如果你在你的析构函数中做的或响应 WM_DESTROY
消息( OnDestroy
在MFC中),它将确保您的每个 CStatic
实例被销毁,解决内存泄漏问题。
If you do this in your destructor or in response to the WM_DESTROY
message (OnDestroy
in MFC), it will ensure that each of your CStatic
instances are destroyed, solving the memory leak problem.
但这不是最好的解决方案。在C ++中,您应该利用,也更通常称为RAII。这涉及到使用语言功能来自动清除对象,而不必手动进行。这不仅使代码更清晰,而且确保你永远不会忘记,你的代码是完全异常安全的,甚至可以更高效。
But this is not the best solution. In C++, you should be taking advantage of Scope-Bound Resource Management (SBRM), also more commonly known as RAII. This involves the use of language features to automatically clean up objects, rather than having to do it manually. Not only does this make the code cleaner, but it ensures that you never forget, that your code is fully exception-safe, and may even be more efficient.
你只需将对象本身存储在容器类中。也就是说,不是 std :: vector< CStatic *>
,你只需要 std :: vector< CStatic>
。这样,当矢量容器被销毁时(由于SBRM,它被超出范围时自动发生),它包含的所有对象也被毁坏( ie ,它们的析构函数被称为自动)。
Typically, you would just store the objects themselves in the container class. That is, instead of std::vector<CStatic*>
, you would just have std::vector<CStatic>
. That way, whenever the vector container is destroyed (which happens automatically when it goes out of scope, thanks to SBRM), all of the objects that it contains get destroyed as well (i.e., their destructors are called automatically).
但是,标准库容器要求对象是可复制的或可移动的。从 CObject
派生的MFC类不是可复制的,并且可能不是可移动的(给定MFC的年龄和使对象不可复制隐含地使其不可复制的标准习语)活动)。这意味着这不会工作:你不能存储 CStatic
对象本身在向量或其他容器类中。
However, the standard-library containers require that objects be either copyable or movable. The MFC classes derived from CObject
are not copyable, and presumably not movable either (given the age of MFC and the standard idioms for making an object non-copyable implicitly making it non-movable). That means this won't work: you can't store CStatic
objects themselves in a vector or other container class.
幸运的是,现代C ++有这个问题的解决方案: [再次,因为它不可复制],您将需要使用不同的智能指针,如。)
(For C++03, since std::auto_ptr
cannot be used in a standard container [again, because it is not copyable], you would need to use a different smart pointer, such as the Boost Smart Pointers library.)
无需手动内存管理,没有更多的内存泄漏,不再头痛。在C ++中工作是从屁股痛苦到快速,有趣,高效的。
No more manual memory-management, no more memory leaks, no more headaches. Working in C++ literally goes from being a pain in the butt to being fast, fun, and efficient.
这篇关于如何释放在孩子diaolog创建的CWin对象,以避免内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!