调用析构函数时清空std :: list抛出异常

时间:2014-05-22 00:09:31

标签: c++ list exception c++11

因此,如果我在程序退出时使用下面的代码,我会在此位置的std :: list中获得异常。这与我是否添加项目无关。

 void clear() _NOEXCEPT
    {   // erase all
 #if _ITERATOR_DEBUG_LEVEL == 2
    this->_Orphan_ptr(*this, nullptr);
 #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

    _Nodeptr _Pnode = this->_Nextnode(this->_Myhead);
    this->_Nextnode(this->_Myhead) = this->_Myhead;
    this->_Prevnode(this->_Myhead) = this->_Myhead;
    this->_Mysize = 0;

    for (_Nodeptr _Pnext; _Pnode != this->_Myhead; _Pnode = _Pnext)
        {   // delete an element
        _Pnext = this->_Nextnode(_Pnode); //Unhandled exception, access violation
        this->_Freenode(_Pnode);
        }
    }

这是我目前使用std :: list的唯一容器,我只有1个... 如果我将std :: list切换到std :: vector,那么它可以正常工作。

#pragma once
#ifndef EVENT_H
#define EVENT_H
#include <delegate.h>
#include <list>
#include <vector>

using fd::delegate;

template<typename... Args>
class Event;

template<typename...Args>
class Event<void(Args...)>
{
 private:
std::list<delegate<void(Args...)>> m_delegates;
 public:
void addListener(const delegate<void(Args...)>& d)
{
    if (d)
    m_delegates.push_back(d);
}

void removeListener(const delegate<void(Args...)>& d)
{
    if (d)
    m_delegates.remove(d);
}

void removeDeadListeners()
{
    for (auto i = m_delegates.begin(); i != m_delegates.end(); i++)
    {
        if (i->empty())
            m_delegates.remove(i);
    }
}

void operator()(Args... args)
{
    for (auto& d : m_delegates)
    {
        d(args...);
    }
}
};

#endif //EVENT_H

任何使用std :: list的方法?

2 个答案:

答案 0 :(得分:3)

我相信你的问题是你在迭代它时会从list中移除项目,但我很惊讶你所编写的代码完全可以编译。

for (auto i = m_delegates.begin(); i != m_delegates.end(); i++)
{
    if (i->empty())
        m_delegates.remove(i);  // <-- This shouldn't compile
}

list::removelist::value_type为参数,而不是list::iterator,因此上述内容无法编译。解决方案是使用list::erase

for (auto i = m_delegates.begin(); i != m_delegates.end(); )
{
    if (i->empty())
        i = m_delegates.erase(i); // get iterator to next element
    else
        ++i;
}

您还可以完全消除循环并使用list::remove_if

m_delegates.remove_if([](decltype(m_delegates)::value_type const& elem) {
    return elem.empty();
});

答案 1 :(得分:0)

我已经确定它只是与它声明的类有关,因为我可以在其他类中使用Event .....我只是困惑因为我从不调用单个方法。我只是修改一个教程代码,以便更轻松地使用我的测试项目。默认构造函数适用于其他类,我可以添加/调用方法,这只是这个......我很难过。

.h

#pragma once
#ifndef D3DAPP_H
#define D3DAPP_H
#pragma warning(push)
#pragma warning( disable : 4005) //Ignore Identical Macro declarations that exist in Windows and DirectX headers
#include <D3D11.h>
#include <D3DX11.h>
#include <Windows.h>
#pragma warning(pop)
#include "GameTimer.h"
#include <string>
#include "Event.h"

class D3DApp
{
public:
    D3DApp(HINSTANCE hInstance);
    virtual ~D3DApp();

    HINSTANCE AppInst() const;
    HWND MainWnd() const;
    float AspectRatio() const;

    int Run();
    /*
        Framework methods. Derived client class overrides these methods
        to implement specific application requirements
    */
    virtual bool Init();
    virtual void Release();
    Event<void(int,int)> OnResize;
    virtual void UpdateScene(float dt) = 0;
    virtual void DrawScene() = 0;
    virtual LRESULT MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    //Convenience overrides for handling mouse input
    virtual void OnMouseDown(WPARAM btnState, int x, int y);
    virtual void OnMouseUp(WPARAM btnState, int x, int y);
    virtual void OnMouseMove(WPARAM btnState, int x, int y);
protected:
    virtual void ApplicationResize(int w, int h);
    bool InitMainWindow();
    bool InitDirect3D();
    void CalculateFrameStats();
protected:
    HINSTANCE mAppInstance;
    HWND mMainWnd;
    bool mAppPaused;
    bool mMinimized;
    bool mMaximized;
    bool mResizing;
    bool mInitialized;
    UINT m4xMsaaQuality;

    GameTimer mTimer;

    ID3D11Device* md3dDevice;
    ID3D11DeviceContext* md3dImmediateContext;
    IDXGISwapChain* mSwapChain;
    ID3D11Texture2D* mDepthStencilBuffer;
    ID3D11RenderTargetView* mRenderTargetView;
    ID3D11DepthStencilView* mDepthStencilView;
    D3D11_VIEWPORT mScreenViewport;

    std::wstring mMainWndCaption;
    D3D_DRIVER_TYPE md3dDriverType;
    int mClientWidth;
    int mClientHeight;
    bool mEnable4xMsaa;
};

#endif //D3DAPP_H

.cpp

#include "d3dApp.h"
#include "Utility.h"
#include <assert.h>
#include <sstream>

D3DApp* g_d3dApp = 0;

LRESULT CALLBACK
MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
    return g_d3dApp->MsgProc(hwnd, msg, wParam,lParam);
}

D3DApp::D3DApp(HINSTANCE hInstance)
    : mAppInstance(hInstance),
    mMainWndCaption(L"D3D11 Application"),
    md3dDriverType(D3D_DRIVER_TYPE_HARDWARE),
    mClientWidth(800),
    mClientHeight(600),
    mEnable4xMsaa(false),
    mMainWnd(0),
    mAppPaused(false),
    mMinimized(false),
    mMaximized(false),
    mResizing(false),
    mInitialized(false),
    m4xMsaaQuality(0),
    md3dDevice(0),
    md3dImmediateContext(0),
    mSwapChain(0),
    mDepthStencilBuffer(0),
    mRenderTargetView(0),
    mDepthStencilView(0)
{
    ZeroMemory(&mScreenViewport, sizeof(D3D11_VIEWPORT));
    g_d3dApp = this;
}


void D3DApp::Release()
{
    ReleaseCOM(mRenderTargetView);
    ReleaseCOM(mDepthStencilView);
    ReleaseCOM(mSwapChain);
    ReleaseCOM(mDepthStencilBuffer);

    if (md3dImmediateContext)
        md3dImmediateContext->ClearState();

    ReleaseCOM(md3dImmediateContext);
    ReleaseCOM(md3dDevice);
    if (g_d3dApp == this)
        g_d3dApp = nullptr;

    mInitialized = false;
}

D3DApp::~D3DApp()
{
    if (mInitialized) Release();
}

float D3DApp::AspectRatio() const
{
    return static_cast<float>(mClientWidth) / mClientHeight;
}

int D3DApp::Run()
{
    MSG msg = { 0 };
    mTimer.Reset();

    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            mTimer.Tick();

            CalculateFrameStats();
            UpdateScene(mTimer.DeltaTime());
            DrawScene();
        }
    }

    return (int)msg.wParam;
}

bool D3DApp::Init()
{
    if (!InitMainWindow())
        return false;

    if (!InitDirect3D())
        return false;

    mInitialized = true;
    return true;
}

void D3DApp::ApplicationResize(int w,int h)
{
    assert(md3dImmediateContext);
    assert(md3dDevice);
    assert(mSwapChain);

    ReleaseCOM(mRenderTargetView);
    ReleaseCOM(mDepthStencilView);
    ReleaseCOM(mDepthStencilBuffer);

    mClientWidth = w;
    mClientHeight = h;

    HR(mSwapChain->ResizeBuffers(1, mClientWidth, mClientHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0));
    ID3D11Texture2D* backBuffer;
    HR(mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer)));
    HR(md3dDevice->CreateRenderTargetView(backBuffer, 0, &mRenderTargetView));
    ReleaseCOM(backBuffer);

    D3D11_TEXTURE2D_DESC depthStencilDesc;
    ZeroMemory(&depthStencilDesc, sizeof(D3D11_TEXTURE2D_DESC));
    depthStencilDesc.Width = mClientWidth;
    depthStencilDesc.Height = mClientHeight;
    depthStencilDesc.MipLevels = 1;
    depthStencilDesc.ArraySize = 1;
    depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;

    if (mEnable4xMsaa)
    {
        depthStencilDesc.SampleDesc.Count = 4;
        depthStencilDesc.SampleDesc.Quality = m4xMsaaQuality - 1;
    } //No MSAA
    else
    {
        depthStencilDesc.SampleDesc.Count = 1;
        depthStencilDesc.SampleDesc.Quality = 0;
    }

    depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
    depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    depthStencilDesc.CPUAccessFlags = 0;
    depthStencilDesc.MipLevels = 0;

    HR(md3dDevice->CreateTexture2D(&depthStencilDesc, 0, &mDepthStencilBuffer));
    HR(md3dDevice->CreateDepthStencilView(mDepthStencilBuffer, 0, &mDepthStencilView));

    md3dImmediateContext->OMSetRenderTargets(1, &mRenderTargetView,mDepthStencilView);

    mScreenViewport.TopLeftX = 0;
    mScreenViewport.TopLeftY = 0;
    mScreenViewport.Width = static_cast<float>(mClientWidth);
    mScreenViewport.Height = static_cast<float>(mClientWidth);
    mScreenViewport.MinDepth = 0.0f;
    mScreenViewport.MaxDepth = 1.0f;

    md3dImmediateContext->RSSetViewports(1, &mScreenViewport);

    //OnResize(w, h);
}

LRESULT D3DApp::MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    //Ignore messages until we have intialized everything
    if (!mInitialized) 
        return DefWindowProc(hWnd, msg, wParam, lParam);

    switch (msg)
    {
    case WM_ACTIVATE:
        if (LOWORD(wParam) == WA_INACTIVE)
        {
            mAppPaused = true;
            mTimer.Stop();
        }
        else
        {
            mAppPaused = false;
            mTimer.Start();
        }
        return 0;
    case WM_SIZE:
        if (wParam == SIZE_MINIMIZED)
        {
            mAppPaused = true;
            mMinimized = true;
            mMaximized = false;
            mTimer.Stop();
        }
        else if (wParam == SIZE_MAXIMIZED)
        {
            mAppPaused = SIZE_MAXIMIZED;
            mMinimized = false;
            mMaximized = true;
            ApplicationResize(LOWORD(lParam), HIWORD(lParam));
        }
        else if (wParam == SIZE_RESTORED)
        {
            if (mMinimized)
            {
                mAppPaused = false;
                mMinimized = false;
                mTimer.Start();
                ApplicationResize(LOWORD(lParam), HIWORD(lParam));
            }
            else if (mMaximized)
            {
                mAppPaused = false;
                mMaximized = false;
                ApplicationResize(LOWORD(lParam), HIWORD(lParam));
            }
            else if (mResizing)
            {
                //We don't want to do stuff while this is going on
            }
            else
            {
                ApplicationResize(LOWORD(lParam), HIWORD(lParam));
            }
        }
        return 0;
    case WM_ENTERSIZEMOVE:
        mAppPaused = true;
        mResizing = true;
        mTimer.Stop();
        return 0;
    case WM_EXITSIZEMOVE:
        mAppPaused = false;
        mResizing = false;
        mTimer.Start();
        if (lParam != 0)
        ApplicationResize(LOWORD(lParam), HIWORD(lParam));
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    case WM_MENUCHAR:
        //Don't beep when we alt-enter
        return MAKELRESULT(0, MNC_CLOSE);
    case WM_GETMINMAXINFO:
        ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 200;
        ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 200;
        return 0;
    case WM_LBUTTONDOWN:
    case WM_MBUTTONDOWN:
    case WM_RBUTTONDOWN:
        OnMouseDown(wParam, LOWORD(lParam), HIWORD(lParam));
        return 0;
    case WM_LBUTTONUP:
    case WM_MBUTTONUP:
    case WM_RBUTTONUP:
        OnMouseUp(wParam, LOWORD(lParam), HIWORD(lParam));
        return 0;
    case WM_MOUSEMOVE:
        OnMouseMove(wParam, LOWORD(lParam), HIWORD(lParam));
        return 0;
    }

    return DefWindowProc(hWnd, msg, wParam, lParam);
}

bool D3DApp::InitMainWindow()
{
    WNDCLASS wc;
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = MainWndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = mAppInstance;
    wc.hIcon = LoadIcon(0, IDI_APPLICATION);
    wc.hCursor = LoadCursor(0, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
    wc.lpszMenuName = 0;
    wc.lpszClassName = L"D3DWndClassName";

    if (!RegisterClass(&wc))
    {
        MessageBox(0, L"RegisterClass Failed!", 0, 0);
        return false;
    }

    RECT R = { 0, 0, mClientWidth, mClientHeight };
    AdjustWindowRect(&R, WS_OVERLAPPEDWINDOW, false);
    int width = R.right - R.left;
    int height = R.bottom - R.top;

    mMainWnd = CreateWindow(L"D3DWndClassName", mMainWndCaption.c_str(),
        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, 0, 0, mAppInstance, 0);

    if (mMainWnd);
    {
        MessageBox(0, L"CreateWindow Failed", 0, 0); 
        return false;
    }

    ShowWindow(mMainWnd, SW_SHOW);
    UpdateWindow(mMainWnd);

    return true;
}

bool D3DApp::InitDirect3D()
{
    //Create the device and device context
    UINT createDeviceFlags = 0;
#if defined(DEBUG) || defined(_DEBUG)
    createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
    D3D_FEATURE_LEVEL featureLevel;
    HRESULT hr = D3D11CreateDevice(
        0,
        md3dDriverType,
        0,
        createDeviceFlags,
        0, 0,
        D3D11_SDK_VERSION,
        &md3dDevice,
        &featureLevel,
        &md3dImmediateContext);

    if (FAILED(hr))
    {
        MessageBox(0, L"D3D11CreateDevice Failed.", 0, 0);
        return false;
    }

    if (featureLevel != D3D_FEATURE_LEVEL_11_0)
    {
        MessageBox(0, L"Direct3D Feature Level 11 unsupported", 0, 0);
        return false;
    }

    HR(md3dDevice->CheckMultisampleQualityLevels(
        DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality));

    assert(m4xMsaaQuality > 0);

    DXGI_SWAP_CHAIN_DESC sd;
    sd.BufferDesc.Width = mClientWidth;
    sd.BufferDesc.Height = mClientHeight;
    sd.BufferDesc.RefreshRate.Numerator = 60;
    sd.BufferDesc.RefreshRate.Denominator = 1;
    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;

    if (mEnable4xMsaa)
    {
        sd.SampleDesc.Count = 4;
        sd.SampleDesc.Quality = m4xMsaaQuality - 1;
    }
    else
    {
        sd.SampleDesc.Count = 1;
        sd.SampleDesc.Quality = 0;
    }

    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.BufferCount = 1;
    sd.OutputWindow = mMainWnd;
    sd.Windowed = true;
    sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
    sd.Flags = 0;

    IDXGIDevice* dxgiDevice = 0;
    HR(md3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice));

    IDXGIAdapter* dxgiAdapter = 0;
    HR(dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&dxgiAdapter));

    IDXGIFactory* dxgiFactory = 0;
    HR(dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgiFactory));

    HR(dxgiFactory->CreateSwapChain(md3dDevice, &sd, &mSwapChain));

    ReleaseCOM(dxgiDevice);
    ReleaseCOM(dxgiAdapter);
    ReleaseCOM(dxgiFactory);

    ApplicationResize(mClientWidth, mClientHeight);

    return true;
}

void D3DApp::CalculateFrameStats()
{
    //Code computes the average frames per second also the average 
    //time it takes to render one frame. These stats
    //are appended to the window caption bar.

    static int frameCnt = 0;
    static float timeElapsed = 0.0f;

    frameCnt++;
    float dt = mTimer.TotalTime() - timeElapsed;
    if (dt >= 1.0f)
    {
        float fps = (float)frameCnt/dt;
        float mspf = 1000.0f / fps; 

        std::wstringstream outs;
        outs.precision(6);
        outs << mMainWndCaption << L"   "
            << L"FPS: " << fps << L"   "
            << L"Frame Time: " << mspf << L" (ms)";
        SetWindowText(mMainWnd, outs.str().c_str());

        frameCnt = 0;
        timeElapsed += dt;
    }
}

void D3DApp::OnMouseDown(WPARAM btnState, int x, int y)
{

}

void D3DApp::OnMouseUp(WPARAM btnState, int x, int y)
{

}
void D3DApp::OnMouseMove(WPARAM btnState, int x, int y)
{

}