C ++ Allocator :: destroy throws

时间:2014-05-23 15:54:03

标签: c++ visual-studio-2012 sfml

编辑:我已经更改了源代码以使用额外的结构而不是那么好的元组。

编辑:这个问题已经解决了,虽然我没有找到原因,但我重建了代码,以便它不依赖于嵌套而是依赖额外的变量检查

新发现,问题在底部!

我已经设置了SFML项目。我有一个简单的类,用于处理周期性事件。

类别:

#ifndef _TIMER_H_
#define _TIMER_H_

#include <SFML/System.hpp>

#include <vector>
#include <functional>
#include <tuple>

namespace lg{
    struct TimerData{
        bool periodic;
        std::function<void()> function;
        sf::Clock clock;
        float timeout;
        float runTime;
        bool toRemove;
        bool stopEss;
    };

    class Timer{
        std::vector<TimerData> vec;
    public:
        Timer() : vec() {}
        Timer(const Timer& t) : vec(t.vec) {}
        Timer(Timer&& t) : vec(std::move(t.vec)) {}
        Timer& operator=(const Timer& t)
        {
            vec = t.vec;
            return *this;
        }

        Timer& operator=(Timer&& t)
        {
            vec = std::move(t.vec);
            return *this;
        }

        void onTimeout(float timeMilliseconds, std::function<void()> callback)
        {
            TimerData dat;
            dat.periodic = false;
            dat.timeout = timeMilliseconds;
            dat.function = callback;
            dat.toRemove = false;
            dat.runTime = 0;
            dat.clock = sf::Clock();
            dat.stopEss = false;

            vec.push_back(dat);
        }

        void onPeriod(float timeMilliseconds, std::function<void()> callback)
        {
            TimerData dat;
            dat.periodic = true;
            dat.timeout = timeMilliseconds;
            dat.function = callback;
            dat.toRemove = false;
            dat.runTime = 0;
            dat.clock = sf::Clock();
            dat.stopEss = false;

            vec.push_back(dat);
        }

        void onPeriod(float timeMilliseconds, float initialDelay, std::function<void()> callback)
        {
            onTimeout(initialDelay, [=](){ onPeriod(timeMilliseconds, callback); });
        }

        void onTempPeriod(float timeMilliseconds, float runFor, std::function<void()> callback)
        {
            TimerData dat;
            dat.periodic = true;
            dat.timeout = timeMilliseconds;
            dat.function = callback;
            dat.toRemove = false;
            dat.runTime = runFor;
            dat.clock = sf::Clock();
            dat.stopEss = true;

            vec.push_back(dat);
        }

        void onTempPeriod(float timeMilliseconds, float initialDelay, float runFor,
                            std::function<void()> callback)
        {
            onTimeout(initialDelay, [=](){
                onTempPeriod(timeMilliseconds, runFor, callback);
            });
        }

        void check()
        {
            bool removeOne = false;
            for(int i = 0; i < vec.size(); ++i)
            {
                auto& a = vec.at(i);

                auto elapsed = a.clock.getElapsedTime().asMilliseconds();

                if (elapsed >= a.timeout)
                {
                    a.function();
                    if (a.periodic)
                    {
                        a.clock.restart();

                        a.runTime -= elapsed;
                        if (a.stopEss && a.runTime <= 0.f)
                        {
                            removeOne = true;
                            a.toRemove = true;
                        }
                    }
                    else
                    {
                        a.toRemove = true;
                        removeOne = true;
                    }
                }
            }

            if (removeOne)
            {
                vec.erase(std::remove_if(vec.begin(), vec.end(),
                    [](const TimerData& t){
                        return t.toRemove;
                    }),
                    vec.end());
            }
        }
    };
}

#endif    //_TIMER_H_

如果您尝试运行:

std::cout << "testing timer:\n";

lg::Timer t;
t.onTempPeriod(500.f, 5000.f, [](){std::cout << "timeout\n"; });

while(1)
{
    t.check();
}

它工作正常,定时器每500毫秒打印一次“超时\ n”,持续5秒,之后没有任何反应。

但是如果你试图运行onTempPeriod的第二次重载:

t.onTempPeriod(500.f, 1000.f, 3000.f, [](){std::cout << "timeout\n"; });

(第一个参数是每次调用lambda的频率 第二个参数是在调用它之前应该等待多长时间 第三个论点是它应该工作多久)

在1秒初始等待时间后,程序弹出“Program.exe已触发制动点”。错误甚至没有命名,而刹车点在这里:retval = HeapFree(_crtheap, 0, pBlock);是free.c文件的第50行。

我跳过代码,执行vec.erase(..., vec.end());时调用错误。在这种特殊情况下,必须对整个矢量进行检测,并在Visual的实现中进行检查。因此它在向量上调用clear(),它调用一些函数,当程序进入Allocator::destroy时,它看起来像:

template<class _Uty>
    void destroy(_Uty *_Ptr)
    {    // destroy object at _Ptr
    _Ptr->~_Uty();
    }

当执行到达_Ptr-&gt; ~_Uty()时,它只是触发刹车点。

对此有何帮助?

要注意,这对所有其他函数完全正常,并且很可能不是因为onTempPeriod中的嵌套插入。通过调用onPeriod的工作onTimeout证明了这一点。

编辑部分:这真的是组合的事情。无论是在函数内部还是在main函数内部,此代码都将始终触发错误。

t.onTimeout(1000.f, [&](){
    t.onTempPeriod(500.f, 1000.f, [](){std::cout << "a\n";});
});

0 个答案:

没有答案