delete_scalar.cpp 中的“_CRTDECL 运算符删除”中的删除触发异常

delete triggers exception in "_CRTDECL operator delete" in delete_scalar.cpp

我正在用 C++ 编写 WinAPI 应用程序。

情况

我在 wWinMain 中初始化 Interface class 并将指向它的指针存储到 GWLP_USERDATA 中,如下所示:

WinMain(...)
{
    ...

    //  INITIALIZE CUSTOM INTERFACE
    Interface* p_inface{new Interface(hWnd)}; // Create class object
    SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(p_inface)); // to retrieve it in callback

    ...
}

我这样初始化它是因为 Interface class 初始化需要 HWND 的子 classed 控件已经存在,我更喜欢我的 classes 在构造函数中自动完全初始化。

在我的 WndProc 回调中,我想像这样删除它:

WndProc(...)
{
    ...

    case WM_NCDESTROY:
    {
        Interface* p_inface{reinterpret_cast<Interface*>(GetWindowLongPtrW(hWnd, GWLP_USERDATA))};
        delete p_inface;
    }
    break;

    ...
}

Interface class header:

class Interface
{
    public:

    Interface(HWND const hWndParam);
    ~Interface();

    private:

    std::shared_ptr<Time> const p_time; // object holding timeframe information
    std::unique_ptr<Calendar> const p_calendar; // object handling calendar interface
    std::unique_ptr<MainMinimize> const p_minimize; // minimize button
    std::unique_ptr<MainClose> const p_close; // close button

    Interface(const Interface&) = delete;
    Interface& operator=(const Interface&) = delete;
};

和class项目文件:

Interface::Interface
(
    HWND const hWndParam // handle to main window
)
    : p_time(std::make_shared<Time>())
    , p_calendar{std::make_unique<Calendar>(p_time, hWndParam)}
    , p_minimize{std::make_unique<MainMinimize>(hWndParam)}
    , p_close{std::make_unique<MainClose>(hWndParam)}
{
}

Interface::~Interface()
{
}

问题

当应用程序尝试 delete WndProcWM_NCDESTROY 中的 p_inface 指针时,我得到指向此处(在 delete_scalar.cpp 中)的异常:

_CRT_SECURITYCRITICAL_ATTRIBUTE
void __CRTDECL operator delete(void* const block) noexcept
{
    #ifdef _DEBUG
    _free_dbg(block, _UNKNOWN_BLOCK); // << EXCEPTION: APPLICATION TRIGGERED BREAKPOINT
    #else
    free(block);
    #endif
}

我不明白为什么。我尝试从内部 objects 中删除 const (没有成功)并在析构函数中重置内部 Interface class objects (这也没有成功)解决问题)。

调试的时候发现WndProc中的指针是正确的,里面的objects除了Timeshared_ptr都已经被擦掉了。不过它们在 WM_DESTROY 消息中完好无损。

在寻找解决方案时,我发现它主要触发人们在堆栈上删除 objects 或将 newdelete[] 混合。 One person提到"Most likely, either the point is not pointing to a valid heap allocated object, the heap has already been deleted or some other code has corrupted the heap."

问题

你能帮我理解我犯了什么错误以及如何修复它以便不再触发异常吗?

问题不在于实际的 Interface 对象(感谢 molbdnilo!),而是基础 classes 之一中处理信息的顺序。

我的所有控件 class 子 class WinAPI 控件都存储在 unique_ptrInterface 对象更深的对象中,依此类推 Interface delete 语句级联析构函数导致所有 unique_ptrs 自动销毁它们的对象。

问题是,当我通过 dwRefData 将 class 的指针(subclassing 控件)潜入它的回调函数时,我也在 deleting 它 WM_DESTROY 消息 - 但由于 unique_ptr 清理发生的时间早于 DESTROY 消息可能到达队列,该对象早已消失。

所以解决方案:不要尝试删除已经由智能指针处理的对象!