0

请参阅下面的重要编辑!

大家好,我无法弄清楚为什么会发生这种段错误。我正在使用 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 但 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::StateManager 内部的状态堆栈顶部的 Troll::State(我正在制作的框架称为 Troll)(这仅仅是一个带有内存分配和 startup() 和 shutdown() 调用的 std::stack 包装器)

抱歉,由于某种原因,命名约定的差异导致了任何混淆,我决定使用_underscores_for_some_reason,但我还没有来得及改变它。提前谢谢,嗯。希望你能解决我的问题,如果我没有提供足够的细节,请告诉我。


编辑:最近升级到 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;
};

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


重要编辑: 似乎实际上是 peek 函数引起了麻烦,但仅在从该keyPressed函数调用时。我通过向 peek() 添加一个参数来发现这一点,以便它打印返回的状态对象的地址以及消息。通过将消息参数设置为调用 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 时才返回不同的地址?有人请帮我解决这个问题!

4

1 回答 1

1

当您检查 mStateManager 是否为 NULL 并且从 mStateManager->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;
};

编辑:我编辑了代码来打印每个分支,它是如何被追踪的。

于 2011-05-11T19:55:11.560 回答