2017-06-03 2 views
2

J'ai eu des problèmes avec un jeu sur lequel je travaillais, où une fois que j'ai ajouté de la musique, il a commencé à segfault dans mon code de chargement de texture, entre 5 et 30 secondes après avoir commencé à jouer . Le mieux que je pouvais trouver était que c'était une sorte de corruption de la mémoire. Après une bonne semaine d'essai infructueux pour le déboguer (en essayant des choses comme GFlags pageheap), j'ai réussi à le réduire au code suivant, qui présente toujours le problème.Mix_PlayMusic causant la corruption de la mémoire

Parfois, cela se casse avec la callstack qui passe par SDL2_mixer.dll, mais cela se produit principalement dans l'appel SDL_CreateTextureFromSurface, car le moteur de rendu est dans un mauvais état. numTextures obtient entre 15000-40000 sur ma machine (Windows 10 x64, avec le programme compilé pour x86). Mon instinct me dit qu'il y a un problème dans mon environnement ou code, plutôt qu'un problème dans SDL lui-même, mais je suis à une perte. Toute aide ou idée serait grandement appréciée.

#include <SDL_image.h> 
#include <SDL_mixer.h> 
#include <cassert> 

int main(int argc, char* argv[]) 
{ 
    assert(SDL_Init(SDL_INIT_EVERYTHING) == 0); 

    SDL_Window * pWindow_ = SDL_CreateWindow(
     "", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0x0); 
    assert(pWindow_ != nullptr); 

    SDL_Renderer * pRenderer_ = SDL_CreateRenderer(pWindow_, -1, 0); 
    assert(pRenderer_ != nullptr); 

    assert(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 512) == 0); 

    Mix_Music * pMusic = Mix_LoadMUS("sounds/tranquility.wav"); 
    assert(pMusic != nullptr); 
    assert(Mix_PlayMusic(pMusic, -1) == 0); 

    SDL_Surface * pSurface = IMG_Load("images/caution.png"); 
    assert(pSurface != nullptr); 
    SDL_Texture * pTexture = SDL_CreateTextureFromSurface(pRenderer_, pSurface); 
    assert(pTexture != nullptr); 

    int numTextures = 0; 
    while (true) 
    { 
     numTextures += 10; 
     assert(pTexture != nullptr); 
     SDL_DestroyTexture(pTexture); 
     pTexture = SDL_CreateTextureFromSurface(pRenderer_, pSurface); 
     assert(pTexture != nullptr); 
    } 
} 
+2

Avez-vous vérifié que 'Mix_LoadMUS()' renvoie un non-NULL 'Mix_Music *'? Les docs ['Mix_PlayMusic()' (https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC57) ne disent rien de la gestion élégante des arguments NULL 'music'. Idem pour votre appel 'IMG_Load()'. – genpfault

+0

@genpfault bonne réflexion. J'ai ajouté des vérifications nuls pour pTexture avant de détruire et après la création, et dans Mix_LoadMUS. J'ai aussi affirmé pour zéro dans Mix_PlayMusic. Aucune de ces affirmations échoue. Et il est intéressant de noter que jusqu'à la panne, la musique joue comme prévu. –

+1

Excellent, merci de vérifier et de mettre à jour le MCVE! Ensuite: avez-vous compilé SDL2, SDL_mixer et SDL_image avec le compilateur de votre choix (je pense à un Visual Studio récent?) Ou utilisez-vous les binaires de libsdl.org? Si vous utilisez les binaires, essayez de les construire localement en mode Debug ou RelWithDebInfo, cela rendra vos backtraces plus compréhensibles. Une autre chose à essayer est d'ajouter un 'SDL_PumpEvents()' à votre boucle while. Désolé, je n'ai rien de mieux, ce que vous avez l'air OK pour moi :( – genpfault

Répondre

1

La solution s'est révélée être mise à jour vers la dernière version de SDL (2.0.3 -> 2.0.5).

J'ai commencé à développer le projet en question avec une base de code moteur que j'ai mise à jour de SDL 1.2 à 2.0 il y a environ 2 ans, lorsque la dernière version était 2.0.3.

Lorsque j'ai récemment ajouté le son et la musique, j'ai pris la dernière SDL_mixer, et je n'ai pas pensé à mettre à jour SDL à la dernière 2.0.5.

Après avoir obtenu les dernières bibliothèques de développement et d'exécution pour SDL (et SDL_image et SDL_mixer pour faire bonne mesure), le problème a disparu.

Je ne suis pas entièrement satisfait de cela. Je suis assez surpris que le plus récent SDL_mixer lié avec succès à un ancien SDL, si elles n'étaient pas compatibles. En outre, je ne trouve aucune ressource en ligne suggérant des problèmes de compatibilité. Par conséquent, je me sens mal à l'aise car il se peut que quelque chose d'autre se soit passé, ce qui a été résolu par la mise à niveau.