0

我有一个模拟程序。在模拟的主要课程中,我正在“创建+添加”和“删除+销毁”代理。

问题是有时(我每运行程序 3-4 次)程序崩溃,因为我显然在主循环中调用了无效代理的函数。该程序大部分时间都运行良好。列表中通常有数千个代理。

  • 我不知道我的循环中怎么可能有无效的代理。
  • 调试代码非常困难,因为我在“Agent::Step 函数”中收到内存异常(为时已晚,因为我无法理解列表中的无效代理是如何被调用的)。

    当我查看 Agent::Step 函数(异常点)中的 Agent 引用时,代理中的任何数据都没有意义,甚至初始化数据也没有意义。所以肯定是无效的。

    void World::step()
    {
        AddDemand();
    
        // run over all the agents and check whether they have remaining actions
        // Call their step function if they have, otherwise remove them from space and memory
        list<Agent*>::iterator it = agents_.begin();
        while (it != agents_.end())
        {
            if (!(*it)->AllIntentionsFinished())
            {
                (*it)->step();
                it++;
            }
            else
            {
                (*it)->removeYourselfFromSpace();  //removes its reference from the space
                delete (*it);
                agents_.erase(it++);
            }
        }
    }
    
    void World::AddDemand()
    {
        int demand = demandIdentifier_.getDemandLevel(stepCounter_);
        for (int i = 0; i < demand; i++)
        {
            Agent*  tmp  = new Agent(*this);
            agents_.push_back(tmp);
        }
    }
    
    Agent:
    
    bool Agent::AllIntentionsFinished()
    {
        return this->allIntentionsFinished_;  //bool flag will be true if all work is done
    }
    

1-VStudio 2012循环优化(即如果可能的话在多线程中运行)是否可能会产生问题?

2-关于调试代码的任何建议?

4

2 回答 2

2

如果您正在多线程运行代码,那么您需要添加代码来保护诸如添加项目和从列表中删除项目之类的事情。您可以相当容易地创建一个为容器添加线程安全性的包装器——拥有一个在您对底层容器执行潜在修改操作时锁定的互斥锁。

template <class Container>
thread_safe {
    Container c;
    std::mutex m;
public:
    void push_back(typename Container::value_type const &t) { 
         std::lock_guard l(m);
         c.push_back(t);
    }
    // ...
};

其他几点:

  1. 您几乎可以肯定地通过直接保存列表来清理您的代码Agent,而不是指向您必须动态分配的代理的指针。

  2. 您的Agent::RemoveYourselfFromSpace外观/听起来很像应该由代理的析构函数处理的东西。

  3. 通过使用一些标准算法,您几乎可以肯定地做更多的事情来清理代码。

例如,在我看来,您step可以这样写:

agents.remove_if([](Agent const &a) { return a.AllIntentionsFinished(); });

std::for_each(agents.begin(), agents.end(),
              [](Agent &a) { a.step(); });

...或者,您可能更喜欢继续使用显式循环,但使用类似:

for (Agent & a : agents)
    a.step();
于 2013-07-20T19:20:43.053 回答
0

问题是这样的:

agents_.erase(it++);

请参阅 在运行时从列表中添加和删除

我在您显示的代码中没有看到任何线程安全组件,因此如果您正在运行多个线程并在它们之间共享数据,那么您绝对可能遇到线程问题。例如,您这样做:

(*it)->removeYourselfFromSpace();  //removes its reference from the space
delete (*it);
agents_.erase(it++);

这是未锁定列表的最差顺序。您应该:按顺序从列表中删除、破坏对象、删除对象。

但是,如果您不是专门创建共享列表/代理的线程,那么线程可能不是您的问题。

于 2013-07-20T19:15:48.013 回答