2015-09-09 55 views
2

在C++上处理快速原型时,我偶然发现了这个错误。现在,我已经读过,代码意味着“访问违规”,但是为什么会出现这种情况的原因或原因完全无法解决。在缩小原因后,我注意到它与我调用某个特定函数有关。然而,有趣的是,代码在调用函数后不会立即崩溃,而是后面的执行结束。换句话说,程序启动,正确执行(即使出现错误的功能看起来按预期工作),,然后,主要完成后,它与该错误代码崩溃。程序结束时进程返回0xC0000005

虽然试图调试我的代码,但我逐行通过了有问题的函数,对每条指令进行了注释,以查看是否有任何内部操作导致程序崩溃。令人惊讶的是,无论我评论哪条指令,代码崩溃。实际上,我已经开始评论函数中的每条指令,给我一个存根,当被调用时什么都不做,而且程序在完成时仍然失败。但是,如果我注释掉本身,程序将停止发布错误代码。因此,唯一合理的解决方案就是根本不会调用它,因为即使调用它并使其无效也不起作用。

我从字面上一无所得。我不知道发生了什么,或者为什么我的代码的行为就像它一样。

仅供参考,我将包含一些可能或可能不是特别重要的片段。

a。以下是违规功能。请注意,在当前状态下,它什么都不做,但调用时代码仍然崩溃。请考虑这是一项免费功能。

void createCollectable(entityx::EntityX& manager, TextureAtlas& atlas, unsigned int type) 
{ 
    /* 
    entityx::Entity collectable = manager.entities.create(); 

    collectable.assign<CollectableComponent>(type); 
    collectable.assign<Scriptable>(std::bind(&collectableCallback, collectable)); 
    collectable.assign<Positionable>(sf::Vector2f(250.0f, 250.0f), sf::Vector2f(1.0f, 1.0f), sf::Vector2f(1.0f, 0.0f)); 
    collectable.assign<Movable>(0.0f, sf::Vector2f(0.0f, -220.0f)); 

    switch(type) 
    { 
    case CollectableIDs::EXTRA_BOMB: 
     collectable.assign<Collidable>(createBoxCollisionShape(Game::collisionWorld, 10.0f, 10.0f, collectable)); 
     collectable.assign<Drawable>(atlas.getFrameAsSprite("EXTRA_BOMB"), 201, sf::BlendAlpha); 
     break; 

    case CollectableIDs::EXTRA_LIFE: 
     collectable.assign<Collidable>(createBoxCollisionShape(Game::collisionWorld, 10.0f, 10.0f, collectable)); 
     collectable.assign<Drawable>(atlas.getFrameAsSprite("EXTRA_LIFE"), 201, sf::BlendAlpha); 
     break; 

    case CollectableIDs::POWER_LARGE: 
     collectable.assign<Collidable>(createBoxCollisionShape(Game::collisionWorld, 10.0f, 10.0f, collectable)); 
     collectable.assign<Drawable>(atlas.getFrameAsSprite("POWER_LARGE"), 201, sf::BlendAlpha); 
     break; 

    case CollectableIDs::SUPER_POWER: 
     collectable.assign<Collidable>(createBoxCollisionShape(Game::collisionWorld, 10.0f, 10.0f, collectable)); 
     collectable.assign<Drawable>(atlas.getFrameAsSprite("SUPER_POWER"), 201, sf::BlendAlpha); 
     break; 

    case CollectableIDs::POWER_MEDIUM: 
     collectable.assign<Collidable>(createBoxCollisionShape(Game::collisionWorld, 7.5f, 7.5f, collectable)); 
     collectable.assign<Drawable>(atlas.getFrameAsSprite("POWER_MEDIUM"), 201, sf::BlendAlpha); 
     break; 

    case CollectableIDs::POWER_SMALL: 
     collectable.assign<Collidable>(createBoxCollisionShape(Game::collisionWorld, 5.0f, 5.0f, collectable)); 
     collectable.assign<Drawable>(atlas.getFrameAsSprite("POWER_SMALL"), 201, sf::BlendAlpha); 
     break; 

    case CollectableIDs::MIASMA_LARGE: 
     collectable.assign<Collidable>(createCircleCollisionShape(Game::collisionWorld, 5.0f, collectable)); 
     collectable.assign<Drawable>(atlas.getFrameAsSprite("POINT_LARGE"), 201, sf::BlendAlpha); 
     break; 

    case CollectableIDs::MIASMA_SMALL: 
     collectable.assign<Collidable>(createCircleCollisionShape(Game::collisionWorld, 5.0f, collectable)); 
     collectable.assign<Drawable>(atlas.getFrameAsSprite("POINT_SMALL"), 201, sf::BlendAlpha); 
     break; 

    default: 
     collectable.assign<Collidable>(createCircleCollisionShape(Game::collisionWorld, 5.0f, collectable)); 
     collectable.assign<Drawable>(atlas.getFrameAsSprite("POINT_SMALL"), 201, sf::BlendAlpha); 
    } 

    return collectable; 
    */ 
} 

b。这里是函数被调用的代码。请注意,如果我在此注释掉对createCollectable的呼叫,代码将成功结束并且不会崩溃。

void Game::run() 
{ 
    loadResources(); 
    prepareActionMap(actionMap); 
    ContactListener contactListener; 
    collisionWorld.SetContactListener(&contactListener); 
    collisionWorld.SetAllowSleeping(false); 

    sf::Time timeSinceLastUpdate = sf::Time::Zero; 

    /*These elements are for testing only, remove them after they're not used*/ 
    createPlayer(manager, actionMap, atlasHolder["player"]); 
    createCollectable(manager, atlasHolder["bullets"], CollectableIDs::SUPER_POWER); 
    createAdminEntity(manager); 

    /*-----------------------------------------------------------------*/ 

    gameClock.restart(); 
    while(window.isOpen()) 
    { 
     timeSinceLastUpdate += gameClock.restart(); 
     while(timeSinceLastUpdate > FPS) 
     { 
      timeSinceLastUpdate -= FPS; 
      processEvents(); 
      update(FPS); 
     } 

     render(FPS); 
    } 
} 

c。只是为了完整性,这里是我如何在我的.hpp文件中声明自由函数。

void createCollectable(entityx::EntityX& manager, TextureAtlas& atlas, unsigned int type); 

d。下面的自由函数,与前一个函数声明几乎完全相同,确实按预期工作,并且不会在调用时异常返回。再次,这是供参考。请注意,使函数返回值与否与调用函数是否抛出没有关系(正如您从第一个函数的注释返回中看到的,这表明它最初返回了一些东西,就像这个函数一样):

entityx::Entity createPlayer(entityx::EntityX& manager, thor::ActionMap<unsigned int>& actionMap, TextureAtlas& playerAtlas) 
{ 
    entityx::Entity player = manager.entities.create(); 

    player.assign<Drawable>(playerAtlas.getFrameAsSprite("IDLE_1", true), 101, sf::BlendAlpha); 
    player.assign<Positionable>(sf::Vector2f(100.0f, 100.0f), sf::Vector2f(1.0f, 1.0f), sf::Vector2f(1.0f, 0.0f)); 
    player.assign<Movable>(0.0f, sf::Vector2f(0.0f, 0.0f)); 
    player.assign<Controllable>(); 

    thor::ActionMap<unsigned int>::CallbackSystem& callbackSystem = (player.component<Controllable>())->callbackSystem; 

    callbackSystem.connect(ActionIDs::LEFT_BUTTON_HELD, std::bind(&moveLeftCallback, player)); 
    callbackSystem.connect(ActionIDs::RIGHT_BUTTON_HELD, std::bind(&moveRightCallback, player)); 
    callbackSystem.connect(ActionIDs::UP_BUTTON_HELD, std::bind(&moveUpCallback, player)); 
    callbackSystem.connect(ActionIDs::DOWN_BUTTON_HELD, std::bind(&moveDownCallback, player)); 
    callbackSystem.connect(ActionIDs::HORIZONTAL_BUTTONS_UNPRESSED, std::bind(&stopHorizontalMovementCallback, player)); 
    callbackSystem.connect(ActionIDs::VERTICAL_BUTTONS_UNPRESSED, std::bind(&stopVerticalMovementCallback, player)); 
    callbackSystem.connect(ActionIDs::FOCUS_BUTTON_PRESSED, std::bind(&focusPlayerCallback, player)); 
    callbackSystem.connect(ActionIDs::FOCUS_BUTTON_UNPRESSED, std::bind(&unfocusPlayerCallback, player)); 

    thor::FrameAnimation playerIdleAnimation; 
    playerIdleAnimation.addFrame(0.25f, playerAtlas.getFrameAsRect("IDLE_1")); 
    playerIdleAnimation.addFrame(0.25f, playerAtlas.getFrameAsRect("IDLE_2")); 
    playerIdleAnimation.addFrame(0.25f, playerAtlas.getFrameAsRect("IDLE_3")); 
    playerIdleAnimation.addFrame(0.25f, playerAtlas.getFrameAsRect("IDLE_4")); 

    thor::FrameAnimation playerMoveLeftAnimation; 
    playerMoveLeftAnimation.addFrame(0.25f, playerAtlas.getFrameAsRect("LEFT_1")); 
    playerMoveLeftAnimation.addFrame(0.25f, playerAtlas.getFrameAsRect("LEFT_2")); 
    playerMoveLeftAnimation.addFrame(0.25f, playerAtlas.getFrameAsRect("LEFT_3")); 
    playerMoveLeftAnimation.addFrame(0.25f, playerAtlas.getFrameAsRect("LEFT_4")); 

    thor::FrameAnimation playerMoveRightAnimation; 
    playerMoveRightAnimation.addFrame(0.25f, playerAtlas.getFrameAsRect("RIGHT_1")); 
    playerMoveRightAnimation.addFrame(0.25f, playerAtlas.getFrameAsRect("RIGHT_2")); 
    playerMoveRightAnimation.addFrame(0.25f, playerAtlas.getFrameAsRect("RIGHT_3")); 
    playerMoveRightAnimation.addFrame(0.25f, playerAtlas.getFrameAsRect("RIGHT_4")); 

    thor::Animator<DrawableAsset, unsigned int> playerAnimator; 
    playerAnimator.addAnimation(AnimationIDs::PLAYER_IDLE, playerIdleAnimation, sf::seconds(0.3f)); 
    playerAnimator.addAnimation(AnimationIDs::PLAYER_MOVE_LEFT, playerMoveLeftAnimation, sf::seconds(0.3f)); 
    playerAnimator.addAnimation(AnimationIDs::PLAYER_MOVE_RIGHT, playerMoveRightAnimation, sf::seconds(0.3f)); 
    playerAnimator.playAnimation(AnimationIDs::PLAYER_IDLE, true); 

    player.assign<Animatable>(playerAnimator); 
    player.assign<Collidable>(createCircleCollisionShape(Game::collisionWorld, 2.5f, player), &onPlayerCollisionCallback); 
    player.assign<Grazeable>(createCircleCollisionShape(Game::collisionWorld, 25.0f, player), &onPlayerGrazeCallback); 
    player.assign<PlayerComponent> 
    (
     3, 
     3, 
     5.0f, 
     3.0f, 
     150.0f, 
     0, 
     0, 
     0.0f, 
     false 
    ); 

    return player; 
} 

对这个问题的任何帮助将不胜感激。我不相信给出一个使用过的库的列表会有什么意义,因为这个问题似乎与其中任何一个都没有关系,但为了完整起见,这里的主要库是SFML,entityx和Box2D。

+4

尽量放在一起能重现问题小例子。这是一个好主意,原因有两个:1)如果你有一个最小的例子,你可能会从这里的人那里得到更多的帮助; 2)通常在创建一个最小的例子的过程中,你可能会发现你正在寻求帮助的问题。 – ilent2

+2

什么是atlas持有人,它在哪里定义?如果您在调用某个其他对象时正在访问无效元素,则可能会破坏您的程序。 – zstewart

+0

我建议你通过将'switch'语句放入表中来处理攻击。访问表的引擎的代码将保持不变,您只需修改表(添加,删除条目)即可。这被称为“数据驱动软件”。是的,表格会简化你的程序。 –

回答

3

看来,collisionWorld具有更长的寿命持续时间较contactListener

ContactListener contactListener; 
collisionWorld.SetContactListener(&contactListener); 

你肯定collisionWorld不访问contactListener它超出范围后? (例如在CollisionWorlddtor)。

尝试在run()函数的末尾添加此:

collisionWorld.SetContactListener(0); 
+0

是的,这似乎是问题所在。我将自由函数更改为更加面向对象的事物,并且在我完成了这个世界之后,确保让听众不再感到沮丧。这似乎缓解了这个问题,因为这个过程现在返回0.非常感谢您的回答。 – Magnaillusion