0

C ++でクロスプラットフォームOpenGLコンテキスト(これはWin7 64ビットにあります)を作成するために、最小限の方法でSDL 1.2を使用しています。また、glew を使用して、コンテキストが OpenGL 4.2 (ドライバーがサポートする) をサポートするようにします。

実行時には問題なく動作しますが、最近、SDL_Quit を呼び出してシャットダウンするときにランダムにクラッシュすることに気付きました。

OpenGL の起動とシャットダウンを伴う SDL (1.2) の適切なシーケンスは何ですか?

これが私が現在していることです:

int MyObj::Initialize(int width, int height, bool vsync, bool fullscreen)
{
  if(SDL_Init( SDL_INIT_EVERYTHING ) < 0) 
  {
    printf("SDL_Init failed: %s\n", SDL_GetError());
    return 0;
  }

  SDL_GL_SetAttribute(SDL_GL_RED_SIZE,          8);
  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,        8);
  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,         8);
  SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,        8);

  SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,        24);
  SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE,          8);
  SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE,           24);

  SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS,  0);
  SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL,  vsync ? 1 : 0);

  if((m_SurfDisplay = SDL_SetVideoMode(width, height, 24, 
                                       SDL_HWSURFACE | 
                                       SDL_GL_DOUBLEBUFFER | 
                                       (fullscreen ? SDL_FULLSCREEN : 0) |
                                       SDL_OPENGL)) == NULL)
  {
    printf("SDL_SetVideoMode failed: %s\n", SDL_GetError());
    return 0;
  }

  GLenum err = glewInit();
  if (GLEW_OK != err) 
    return 0;

  m_Running = true;
  return 1;
}

int MyObj::Shutdown()
{   
  SDL_FreeSurface(m_SurfDisplay);
  SDL_Quit();

  return 1;
}

init 呼び出しと shutdown 呼び出しの間に、多数の GL リソース (テクスチャ、VBO、VAO、シェーダーなど) を作成し、各フレームの最後に SDL_GL_SwapBuffers() を使用してシーンをレンダリングします (かなり典型的です)。そのようです:

int MyObject::Run()
{
  SDL_Event Event;

  while(m_Running) 
  {
    while(SDL_PollEvent(&Event))
    { OnEvent(&Event); } //this eventually causes m_Running to be set to false on "esc"

    ProcessFrame();
    SDL_SwapBuffers();
  }
  return 1;
}

~MyObject 内で MyObject::Shutdown() が呼び出されます。最近 SDL_Quit がアプリをクラッシュさせたところ。また、レンダー ループが同じ効果に戻った後、デストラクタの外側で Shutdown を呼び出すことも試みました。

私がしないことの 1 つ (私がする必要があるとは思わなかった) は、Shutdown を呼び出す前に、割り当てられたすべての GL リソースに対して glDelete* 関数を呼び出すことです (コンテキストの破壊によって自動的にクリーンアップされると思っていましたが、これは SDL_FreeSurface または SDL_Quit() の実行中に発生していると想定していました.もちろん、ラッピング オブジェクトの dtors で glDelete* 関数を呼び出します.これは最終的に ~MyObject の物語によって呼び出されます. MyObject のメンバー。

実験として、Shutdown() の前にすべての適切な glDelete* 呼び出しを強制的に実行しようとしましたが、クラッシュは発生していないようです。面白いことに、1 週間前にこれを行う必要はありませんでした。GIT によると、実際には何も変更されていません (ただし、間違っている可能性があります)。

SDL で MyObject::Shutdown を呼び出す前に、すべての GL リソースが解放されていることを確認する必要がありますか? 他に何か間違ったことをしているように見えますか?

4

1 に答える 1

3
m_SurfDisplay = SDL_SetVideoMode(...)
...
SDL_FreeSurface(m_SurfDisplay);
                ^^^^^^^^^^^^^ naughty naughty!

SDL_SetVideoMode():

返されたサーフェスは SDL_Quit によって解放され、呼び出し元によって解放されてはなりません

于 2013-10-12T05:33:01.187 に答える