当几乎相同的函数工作时,C ++ OIS Segfault

时间:2011-05-11 19:45:45

标签: c++ segmentation-fault ogre

请参阅下面的重要编辑内容!

大家好我无法弄清楚为什么会发生这种段错误。我正在使用Ogre和OIS库。以下是导致它的代码:

bool Troll::Application::keyPressed(const OIS::KeyEvent& event) {
    //TODO: Segfault here!
    Troll::State* state = mStateManager->peek();
    state->key_pressed(event); //This causes the SEGFAULT!!!
    return true;
};

key_pressed函数:

void Troll::RootState::key_pressed(const OIS::KeyEvent& event) {
    std::cout << "You got here" << std::endl; //this isnt printed!
    std::cout << "Key Pressed: " << event.key << std::endl;
};

因为在key_pressed上发生了segfault,但是key_pressed的第一行没有被执行,我只能猜测它正在传递导致它的const OIS::KeyEvent&

关于这一点的奇怪之处在于我还有其他三个几乎完全相同的功能(但对鼠标而言)可以完美运行。

bool Troll::Application::mouseMoved(const OIS::MouseEvent& event) {
    mStateManager->peek()->mouse_moved(event);
    return true;
};
void Troll::RootState::mouse_moved(const OIS::MouseEvent& event) {
    std::cout << "Mouse Moved: rel x = " << event.state.X.rel << std::endl;
    std::cout << "             rel y = " << event.state.Y.rel << std::endl;
    std::cout << "             abs x = " << event.state.X.abs << std::endl;
    std::cout << "             abs y = " << event.state.Y.abs << std::endl;
};

我正在创建一个基本的状态系统,所以我可以使用OIS库开始为Ogre3D编写应用程序以进行输入。我有一个Application类,它充当鼠标和键盘的输入监听器。以下是它的设置......

void Troll::Application::setup_ois() {
    //create a parameter list for holding the window handle data
    OIS::ParamList pl;
    size_t windowHnd = 0;
    //we need the window handle to setup OIS
    std::ostringstream windowHndStr;
    mWindow->getCustomAttribute("WINDOW", &windowHnd);
    windowHndStr << windowHnd;
    //add the handle data into the parameter list
    pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
    //create the input system with the parameter list (containing handle data)
    mInputManager = OIS::InputManager::createInputSystem(pl);
    //true in createInputObject means we want buffered input
    mKeyboard = static_cast<OIS::Keyboard*>(mInputManager->createInputObject( OIS::OISKeyboard, true ));
    mMouse = static_cast<OIS::Mouse*>(mInputManager->createInputObject( OIS::OISMouse, true ));
    //set this as an event handler
    mKeyboard->setEventCallback(this);
    mMouse->setEventCallback(this);
};

应用程序类将鼠标移动,按下按钮和击键中继到状态堆栈顶部的Troll :: State(我正在制作的框架称为Troll),该堆栈位于Troll :: StateManager内部(仅仅是带有内存分配和startup()和shutdown()调用的std :: stack的包装器

很抱歉,由于某种原因,我决定使用use_underscores_for_some_reason而命名约定的差异引起的任何混淆,我还没有改变它。在此先感谢,ell。希望你能解决我的问题,如果我没有提供足够的细节,请通知我。


编辑: 在最近升级到Ubuntu Natty Narwhal后,我无法使调试器正常工作,它只是崩溃了计算机。我使用Code :: Blocks并且我不知道如何在IDE之外使用调试器或编译器(我知道很难过,但有一天我会学习)。很抱歉,我无法使用调试器。


编辑: 回应GMan的评论,即使我检查null,我仍然会得到段错误

bool Troll::Application::keyPressed(const OIS::KeyEvent& event) {
    //TODO: Segfault here!
    Troll::State* state = mStateManager->peek();
    if(state == 0) {
        std::cout << "State is null!" << std::endl;
    };
    state->key_pressed(event);
    return true;
};

虽然我不确定这是检查null的正确方法吗?此外,使用peek()的其他方法也能正常工作。再次感谢! :)


重要编辑: 事实上,它实际上是导致故障的peek函数,但只有在从keyPressed函数调用时才会出现问题。我通过向peek()添加一个参数来发现这一点,以便它将打印它返回的状态对象的地址以及消息。通过将message参数设置为调用peek()函数的函数,我得到了这些结果。

Root state is: 0x8fdd470
Peeking state... 0x8fdd470 from: Application::frameRenderingQueued()
Peeking state... 0x8fdd470 from: Application::mouseMoved
Peeking state... 0x8fdd470 from: Application::frameRenderingQueued()
Peeking state... 0x8fdd470 from: Application::frameRenderingQueued()
Peeking state... 0x8fdd470 from: Application::frameRenderingQueued()
Peeking state... 0x936cf88 from: Application::keyPressed
Segmentation fault

请注意,当keyPressed函数调用peek方法时,会显示不同的地址。我不明白为什么只有当keyPress函数调用peek时才返回不同的地址?有人请帮帮我!

1 个答案:

答案 0 :(得分:1)

检查mStateManager是否为NULL,以及从mStateManager-&gt; peek()返回NULL时会发生什么?

bool Troll::Application::keyPressed(const OIS::KeyEvent& event) {
    if (mStateManager == NULL) {
        //! set breakpoint on next line
        std::cout << "mStateManager is NULL, returning false" << std::endl; 
        return false;
    }
    std::cout << "about to call peek" << std::endl;
    if (Troll::State* state = mStateManager->peek())
    {
        std::cout << "about to call key_pressed" << std::endl;
        state->key_pressed(event); //Does this still cause a SEGFAULT?
        std::cout << "back from key_pressed" << std::endl;
        return true;
    }
    std::cout << "mStateManager->peek() returned NULL, returning false" << std::endl; 
    return false;
};

编辑:我编辑了代码以打印每个分支,以及如何跟踪它。