理解微软的内存泄漏检测输出

时间:2017-01-31 18:48:07

标签: c++ visual-studio memory-leaks

对不好的标题感到抱歉,但我只是好奇究竟是什么内存泄漏分别是我真的可以说我在我的程序中做了一些不好的事情。

我在Visual Studio中运行了内存泄漏测试(_CrtDumpMemoryLeaks())并输出了大量检测到的泄漏(只显示了一小部分):

{1640} normal block at 0x081C2AB0, 4 bytes long.
 Data: <;   > 3B 00 00 00 
{789} normal block at 0x08B792E8, 12 bytes long.
 Data: <            > 00 00 00 00 00 00 00 00 00 00 00 00 
{788} normal block at 0x027E62D8, 32 bytes long.
 Data: <         L   L  > 20 A8 FE 07 A0 A0 17 08 E4 4C F3 07 D8 4C F3 07 
{787} normal block at 0x027E6328, 32 bytes long.
 Data: <layer03 - Object> 6C 61 79 65 72 30 33 20 2D 20 4F 62 6A 65 63 74 
{786} normal block at 0x08B79748, 8 bytes long.
 Data: <`N      > 60 4E F3 07 00 00 00 00

我无法弄明白,究竟我做错了什么。我跟随another question of mine的tipps并用智能指针替换了所有new/delete个东西(或者至少我认为我做过)。

我问的原因是,因为我在运行程序时遇到了内存大小和堆大小的增加,我不确定,是否是一些严重问题或者只是某种基本行为。

以我的(自编)gui为例:

std::shared_ptr<Gui_Button> gui_modal_window_map_saved_button;

我现在称之为:

gui_modal_window_map_saved_button.reset(new Gui_Button(res_handler, "Select", 20, 345, 70, 40, BUTTON_CONFIRM));

被告知是内存安全的。现在,有一些我不太确定的事情 - 我现在如何安全地删除按钮?我知道,没有什么比删除智能指针更好,但我想删除不再需要时删除按钮的方式,即在相应的窗口关闭后。

目前我正在使用reset()

“删除”我的按钮
if (g_ev.event_id == EVENT_CLICKED && g_ev.element == gui_modal_window_map_saved_button.get()) {
        gui_modal_window_map_saved.reset();
        gui_modal_window_map_saved_button.reset();
    }

我认为这没关系,但每次创建“新”按钮时,为什么我的内存大小会增加(而不是再次减少)?

回到原来的问题

我得到Visual Studio的这些内存泄漏转储,但我真的无法弄清楚如何使用这些信息。究竟是什么导致内存泄漏?我现在只使用“普通”指针,我需要将一些东西传递给另一个类,即用智能指针替换所有new/deletes。我真的无法显示我的代码,因为它到目前为止大约有3000行..

那么,究竟是什么导致内存泄漏?我如何使用VS提供的信息?

2 个答案:

答案 0 :(得分:0)

Microsoft提供了有关如何利用您所看到的数据的详细信息:https://msdn.microsoft.com/en-us/library/x98tx3cf.aspx

可以使用分配编号在分配时中断代码。在调试输出的以下行中:

{789} normal block at 0x08B792E8, 12 bytes long.

789是分配编号。你提到内存使用正在增长。除非在您进行更长时间的会话时泄漏消息相应增加,否则这并不一定与日益增长的泄漏有关。

要考虑的另一件事是你的班级内发生了泄漏。如果在您的对象中分配了任何未正确处理的元素,则没有智能指针可以保存您。

答案 1 :(得分:0)

C ++与许多新语言的不同之处在于它没有所谓的垃圾收集器。您使用new分配(声明)内存并使用delete显式解除分配(释放)内存。

如果忘记delete,只有在程序存在后操作系统才会释放内存。

为了平衡new的使用和delete的使用,如果可能的话,只在构造函数中分配内存并在(虚拟)析构函数中释放它。这样,如果拥有一块堆内存的对象(用new分配的内存)超出范围(例如离开函数时的局部变量),则内存将自动释放。

顺便说一下,以这种方式分配和释放内存是C ++的多功能性和速度之一。所以它是一种资产,而不是一种可以避免的东西。但需要谨慎使用。