【问题标题】:C++ Unhandled exception: An invalid parameter was passed to a function that considers invalid parameters fatalC++ 未处理异常:将无效参数传递给认为无效参数致命的函数
【发布时间】:2015-06-07 08:36:09
【问题描述】:

我在学校做一个小组项目,我们正在创建一个 2d 游戏,但我遇到了一个异常,我不知道该怎么办。

附注:所有这些都是在调试模式下完成的。

我们有一个物理引擎类,可以计算碰撞并向实体添加矢量力,代码:

void PhysicsEngine::doPhysicsTick()
{
    vector<vector<unordered_set<Entity*>>> *grid = this->grid.getGrid();
    unordered_set<Entity*>* updatable = new unordered_set<Entity*>();
    unordered_set<Entity*>* collidable = new unordered_set<Entity*>();

    const int &r = CollisionGrid::C_GRID_RADIUS;

    for (int row = 0; row < grid->size(); row++)
    for (int col = 0; col < grid->at(row).size(); col++)
    {
        collidable->clear();

        // put all surrounding grid blocks in a entity list to
        // check against collision with the current block

        int rw(row - r > 0 ? row - r : 0);
        int cl(col - r > 0 ? col - r : 0);

        for (int rrow = rw; rrow <= row + r && rrow < grid->size(); rrow++)
        for (int rcol = cl; rcol <= col + r && rcol < grid->at(rrow).size(); rcol++)
            for (Entity *e : grid->at(rrow).at(rcol)) // It crashes here
                collidable->insert(e);

        for (Entity *e : grid->at(row).at(col))
        {
            if (e->isFixed())
                continue;

            e->speed += gravity;

            eBounds.reBox(e->location, e->getSize() + e->speed);

            for (Entity *c : *collidable)
                if (isOverlapping(eBounds, Box(c, c->getSize())) && e != c)
                    doCollision(e, c);

            updatable->insert(e);
        }
    }

我们有一个单独的碰撞网格类来管理我们存储实体以进行碰撞检查的网格(因此我们不必检查所有内容)

碰撞网格及其底层vector 是在物理引擎的构造函数被调用PhysicsEngine::PhysicsEngine(World *world) : grid(world) 时创建的。但出于某种原因,仅在第一个刻度上,我看到矢量网格指向循环内部不存在的东西(尺寸大得离谱等),填充可碰撞。

它抛出的错误在标题中。如果我在它周围放置一个 catch 块,它只会在某些 c++ 库中的其他地方随机崩溃(每次不同的文件)

如果我不评论我放在那里的东西,由于某种原因,它会在我们的 gameloop 类(物理引擎的调用滴答声)析构函数中崩溃。

Gameloop::~Gameloop()
{
    //if( t ) // t = #include <thread>
    //  delete t;
}

我们不允许使用 Win32 API 之外的任何库和一些默认的 c++ 库


编辑:我添加了一些图片(并且取消了 unordered_sets 的动态分配)

它应该显示什么:

它有时会在第一个刻度上显示: (注意指针是一样的,前两次投篮是在同一次跑动中投的)

它在第一次滴答时显示的其他时间:

【问题讨论】:

  • 您是否有任何理由动态分配 STL 容器?
  • @DavidHaim 我希望在堆栈上节省一些空间,尽管我什至不确定它是否能做到(我们的老师并没有准确地给我们关于这个主题的太多信息)
  • 您不会节省那么多,因为大多数容器(std::array 是一个例外)无论如何都会动态分配其内容。容器类本身很少超过几个指针。内容不在堆栈中。
  • 检查您的索引。它们几乎肯定是越界的。
  • @LightningRacisinObrit 但为什么呢?他们不应该与我正在做的所有i &lt; grid-&gt;size() 在一起

标签: c++


【解决方案1】:

您的程序是否处理任务?因为this 在这种情况下可能会解决您的问题(这类异常永远不会在正确的时间使程序崩溃!)

如果没有,那么您需要再调试一下程序。就像每次在崩溃的行之前打印rrowrrcolgrid-&gt;size()grid-&gt;at(rrow)-&gt;size

但我的钱是在代码的并发/内存管理方面。它在删除部分的析构函数中崩溃的事实使我认为您可能正在处理已在其他地方删除的项目,或者在没有适当措施的情况下同时处理项目。在您的屏幕截图中,您有一堆size=???,这可能意味着您的项目/实例已被删除,并且您的指针指向可用内存,从而在循环中访问它时导致崩溃。这是一个很难解决的错误。

此外,您应该能够在调试器中访问异常的参数,如果可以的话,也许您可​​以发布它的所有内容?

【讨论】:

  • 我可能对此不是很清楚,但是,如果我取消注释析构函数中的删除并让它运行,则会弹出错误但它实际上并没有破坏程序(这很高兴只是继续迭代和滴答)这就是为什么我特别说它只发生在第一个滴答声上。并且在第一个错误滴答之后发生的一切都是正常的预期行为。抱歉,for 循环没有缩进,当我查看双行列时,我只看到一个循环,这样对我来说更具可读性。
  • 显然你的钱是对的,因为我在某个地方做了一个Gameloop g(world),然后它就死了,仍然无法解释为什么它会继续运行,但感谢您为我指明了正确的方向!
  • @WhiteNightFury 如果有帮助的话,我在 Xbox 编程中遇到了类似的问题,我必须确保绝对所有对异步 API 的调用都必须有一个 create_task(call_ret_value).then(...) 并带有 try / catch 任何异常抛出。无论如何,异常的disassembleMe 参数应该指向问题所在,如我答案中的链接所示。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 1970-01-01
相关资源
最近更新 更多