2015-09-09 56 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