Programme en C avec SDL plante très souvent !
Répondre à la discussion
Affichage des résultats 1 à 21 sur 21

Programme en C avec SDL plante très souvent !



  1. #1
    AmigaOS

    Programme en C avec SDL plante très souvent !


    ------

    Bonjour

    Je suis en train de faire un petit jeu de plate-forme, en me servant de la bibliothèque SDL.
    Tout fonctionne.
    Seulement quand je veux :
    - déplacer la fenêtre
    - minimiser la fenêtre
    - faire une capture d’écran
    - appuyer sur la croix
    Mon jeu s’arrête dans la dernière position et au bout de quelques secondes vient :
    mon_jeu.exe ne répond pas
    Si vous fermez le programme vous risquez de perdre des informations.
    Et quand je lance mon jeu, alors 1 fois sur 3 le plantage vient directement.
    Avez vous une idée de ce qui ce passe ?

    Merci

    -----

  2. #2
    invite91d45a03

    Re : Programme en C avec SDL plante très souvent !

    La librairie SDL est par nature assez lente et couteuse en cycle CPU, due à un modéle de développement en pile (eg SDL -> directx -> driver -> matériel) par exemple sous MSWindows.

    Quel est ton O.S et le compilateur/IDE employé ?

    Car ce que tu devrais veiller à faire ces optimiser le code généré en activant toute les options d'optimisation de code dans les options du compilateur, SI ton jeux n'est pas destiné a de machines ayant un modéle de CPU trop inférieur au tient.

    Cela te permettra d'avoir un exécutable plus rapide et performant.
    Mais cela peut aussi bien venir d'une mauvaise gestion des allocations de mémoire, ou d'un segment fault.
    Aprés je sais pas je n'est pas la source de ton jeux sous les yeux.

  3. #3
    phoenix440

    Re : Programme en C avec SDL plante très souvent !

    Salut,
    C'est sans doute une mauvaise allocation mémoire ou un truc du style division par 0.
    Visiblement, tu as le problème quand ton OS met l'application en pause.

  4. #4
    AmigaOS

    Re : Programme en C avec SDL plante très souvent !

    Rebonjour

    (Excusez moi de répondre si tard, je n’ai pas vu que j’avais des réponses...)

    Je ne savait pas que SDL était si lent. J’ai entendu qu’il est bas niveau, alors je me suis dit qu’il serait rapide!...

    Mon OS : Windows 7
    IDE : DevC++

    Pour les optimisations, je viens d’essayer comme vous avez dit mais ça ne change rien.

    Le jeu s’arête aussi quand je débranche le câble d’alimentation du PC pendant seulement quelques secondes (j’ai un pc portable).
    J’ai l’impression qu’il s’agit d’un espèce de watshdog qui se dit : Y a quelque chose qui tourne en boucle et qui met longtemps, donc c'est pas normal, donc on arête tout et affiche une erreur...

  5. A voir en vidéo sur Futura
  6. #5
    Dlzlogic

    Re : Programme en C avec SDL plante très souvent !

    Bonjour,
    Vous pouvez nous montrer votre code et on pourra voir s'il y a quelque-chose qui parait bizarre.

  7. #6
    AmigaOS

    Re : Programme en C avec SDL plante très souvent !

    Le code pour mon jeu est trop long (plus de 1000lignes). Par contre j’ai fais un autre programme plus petit se basant un peu sur le même code que mon jeu.
    Si je met la seule fonction en commentaire, le programme a les même beuges que mon jeu (mais n’affiche donc rien). Si je ne le fais pas, le programme s’enlève de-suite.
    J'envoi tout le projet en pièce jointe (fichier projet pour DevC++). Je pense que l’erreur pourrait venir des fonctions (définition, déclaration...)

    Le programme que j’envoi, permet en faite d’afficher un numéro (en INT = 5 chiffres max en décimal), qui s’incrément à chaque fois qu’on clique dans la fenêtres.
    Fichiers attachés Fichiers attachés

  8. #7
    JPL
    Responsable des forums

    Re : Programme en C avec SDL plante très souvent !

    La pièce jointe contenant un exécutable la modération tient à rappeler que son usage fera aux risques et périls de l’utilisateur. Toutefois http://www.virustotal.com/ n'y a trouvé aucun fichier suspect en testant avec 43 antivirus.
    Rien ne sert de penser, il faut réfléchir avant - Pierre Dac

  9. #8
    Dlzlogic

    Re : Programme en C avec SDL plante très souvent !

    Je n'ai pas essayé d'exécuter le .exe, ça n'aurait servi à rien.
    Je ne peux pas non plus compiler le programme, puisque je n'ai pas le SDL.h.
    Par contre, il me semble que vous faites trop d'appels au dessin, c'est à dire trop d'appels à SDL.
    En gros, il devrait y avoir l'initialisation, puis seulement un rafraichissement dans la boucle.
    Vous devriez limiter la valeur maximale de compte.
    Pour le décodage de compte, il me semble que il serait plus rapide de faire
    Code:
    char val[8];
    strcpy(val,itoa(compt));
    for (int i=0; i<strlen(val); i++
    {
      a=val[i]-48;
    ...
    }
    ou quelque-chose comme ça.
    Je suppose que les quelques ligne qui suivent SDL_WaitEvent(&ev); sont décrites comme exemple, mais comme je n'ai aucune indication sur ce que ça fait exactement, je n'en sais pas plus. En tout cas, il est probable que la suite de la séquence s'exécute quoi qu'il arrive.
    En fait, je suis presque sûr que si la séquence de dessin faisait l'objet d'une fonction appelée uniquement si nécessaire, ça résoudrait beaucoup de problèmes.
    En fait, tout dépend de ce que fait cette fonction WaitEvent. Disons que pour moi, elle fait double emploi avec votre while.

  10. #9
    AmigaOS

    Re : Programme en C avec SDL plante très souvent !

    Bonjour

    Merci pour le code beaucoup plus simple, qui travail sur l'ASCII.

    Maintenant j’ai totalement réduit le code. Mon programme ne sert plus qu’a afficher une image à 2 positions différentes en changeant tout les 200ms. Et ça beuge autant !
    Voila mon nouveau code qui fait qu’une page de prog. (+les sdl.h), en pièce jointe.

  11. #10
    AmigaOS

    Re : Programme en C avec SDL plante très souvent !

    Voila la pièce jointe
    objet.zip

  12. #11
    Dlzlogic

    Re : Programme en C avec SDL plante très souvent !

    Bonjour,
    D'abord, j'ai modifié un peu le main
    Code:
    int main(int argc, char *argv[])
    {
    ///////////////////////////////////////// VARIABLES (chargement) :
    
        int cont=1, compt=0, a, b ;
        Uint32 tp_p, tp_a ;
    
        SDL_Event ev ;
    
        SDL_Surface *ecran = NULL ;
        SDL_Surface *affiche = NULL ;
        SDL_Surface *chiffres = NULL ;
        SDL_Surface *ch = NULL ;
    
        SDL_Rect pos_affiche ;
        SDL_Rect pos_chiffres ;
        SDL_Rect pos_ch ;
    
    ///////////////////////////////////////// Debut
    
        SDL_Init (SDL_INIT_VIDEO) ;                        // Chargement SDL
        SDL_WM_SetCaption ("Numeros", NULL) ;         // titre :
        ecran = SDL_SetVideoMode (640, 480, 32, SDL_SWSURFACE);  //|SDL_NOFRAME|SDL_FULLSCREEN|SDL_DOUBLEBUF
        // Ouverture de fenetre + récupération de celle ci dans "ecran"
    
    ///////////////////////////////////////// Création des surfaces normals :
    
        SDL_FillRect (ecran, NULL, SDL_MapRGB (ecran->format, 0, 0, 0)) ;           // Mise en mémoire(Création des couleurs) ;
    
        ecran = SDL_CreateRGBSurface (SDL_SWSURFACE, 320, 240, 32, 0, 0, 0, 0) ;
        affiche = SDL_CreateRGBSurface (SDL_SWSURFACE, 40, 13, 32, 0, 0, 0, 0) ;
    
    ///////////////////////////////////////// Chargement Images :
    
        chiffres = SDL_LoadBMP ("chiffres.bmp") ;
    
    ///////////////////////////////////////// Transparances :
    
        //SDL_SetColorKey (affiche, SDL_SRCCOLORKEY, SDL_MapRGB (ecran_1->format, 255, 255, 255)) ;
    
    ///////////////////////////////////////// Initialisations :
    
        pos_affiche.x = 20 ;
        pos_affiche.y = 15 ;
    
    ///////////////////////////////////////// Boucle :
    
        SDL_EnableKeyRepeat (10, 10) ;                                    // Répéter l'appui du bouton tout les x ms si celuici enfoncé
    
      while (cont)
      {
        tp_p = SDL_GetTicks () ;
    
                   SDL_WaitEvent (&ev) ;
                   switch(ev.type)
                   {
                     case SDL_QUIT           : cont = 0 ; break ;
                     case SDL_MOUSEBUTTONUP  :
                       compt++ ;
                       Traitement();
                       break;
                     case SDL_KEYDOWN:
                       switch (ev.key.keysym.sym)
                       {
                          case SDLK_ESCAPE :
                          case SDLK_c  : compt = 0 ;
                       }
                   }
    /////////////////////////////////////////NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
      }
    ///////////////////////////////////////// Libération mémoire + Fin :
    
        SDL_FreeSurface (ecran) ;
        SDL_FreeSurface (affiche) ;
        SDL_FreeSurface (ch) ;
        SDL_FreeSurface (chiffres) ;
    
        SDL_Quit() ;
    
        return EXIT_SUCCESS ;
    }
    
    ////////////////////////////////////////////////////////////////////////////////// Fonctions :
    
    void Traitement(int compt)
    {
      char val[8];
      strcpy(val,itoa(compt));
      for (int i=0; i<strlen(val); i++
      {
        int a=val[i]-48;
        SDL_Surface *ch = select(a, chiffres) ;
        pos_ch.x = 0 ; pos_ch.y = 0 ;
        SDL_BlitSurface (ch, NULL, affiche, &pos_ch) ;
        SDL_FillRect(affiche, NULL, SDL_MapRGB (affiche->format, 255, 255, 255)) ;
        SDL_FillRect(ecran, NULL, SDL_MapRGB (ecran->format, 255, 255, 255)) ;
    
    ///////////////////////////////////////// Blitages :
    
        SDL_BlitSurface (affiche, NULL, ecran, &pos_affiche) ;          // Blittage AlienJ //
    
        SDL_Flip (ecran) ;
    
    ///////////////////////////////////////// Calculs fin boucle :
    
        tp_a = SDL_GetTicks () ;
        SDL_Delay (30 - tp_a + tp_p) ;
    }
    Ce qui est important est que dans la boucle while (cont) il ne doit pas y avoir de traitement en dehors du switch(ev.type)

    Vous remarquerez que j'ai supprimé les "break;" inutiles. Ca ne change rien, mais ça aide à comprendre ce qui se passe.

    Donc, quand l'utilisateur a relâché le bouton de la souris qu'il fallait, on lance une fonction "traitement".
    Mais attention, on appuie toujours avant de relâcher. Comme je ne connais pas SDL il y a des détails dont je ne suis pas sûr.

    Dans votre nouveau main, vous affichez sans arrêt un objet, à un certain moment la machine en a assez.
    In est indispensable de bien comprendre que on travaille dans une organisation "évènementielle" C'est à dire que la machine attend un évènement, s'il n'y en a pas, elle continue. Si elle continue sans rien avoir à faire, tout va bien, par contre si à chaque passage dans la boucle, c'est à dire en permanence, vous lui demandez une opération longue, elle finit par se lasser.

    J'ai quelques doutes sur certains points de syntaxe, entre autre sur la manière d'utiliser les pointeurs.

  13. #12
    AmigaOS

    Re : Programme en C avec SDL plante très souvent !

    Merci pour avoir refait la moitié ce programme , mais en ce moment je suis très occupé avec mes études...
    Je vais bientôt tester le code...

  14. #13
    Chanur

    Re : Programme en C avec SDL plante très souvent !

    Bonjour,
    Je n'ai pas essayé le code (je ne connais pas SDL) mais les variables tp_a et tp_p utilisées dans Traitement ne sont pas déclarées => ça ne peut pas marcher.
    @+

  15. #14
    Dlzlogic

    Re : Programme en C avec SDL plante très souvent !

    @Chanur
    Vous savez, on est dans un contexte C, alors la moindre absence de déclaration ne peut pas passer inaperçue.
    C'est moi qui ai modifié le code, donc c'est moi le seul responsable.
    Mais le difficulté n'est pas un problème de compile, mais d'exécution : le traitement est long et le programme se plante.

  16. #15
    bzh_nicolas

    Re : Programme en C avec SDL plante très souvent !

    Quelque remarques sur le code posté par dlzlogic (et surement pas compilé...) :

    Code:
    case SDL_MOUSEBUTTONUP  :
      compt++ ;
      Traitement();
      break;
    Vu le prototype de Traitement, il faudrait lui passer un argument.

    Code:
    char val[8];
    strcpy(val,itoa(compt));
    Comme compt est un int, que l'on est sur des proc 32 bits (voire plus) et que la fin du while n'est pas conditionné à la valeur haute de cont (ni de compt d'ailleurs) il faudrait plutôt déclaré ainsi :
    Code:
    char val[11];
    Soit 10 caractères pour stocker le nombre et le onzième pour le '\0'
    Il serait bien également de faire un test à un moment ou un autre sur la valeur de compt pour éviter de dépasser la valeur max d'un int (peu de risque ici mais ça n'est pas plus mal de prendre de bonnes habitudes).

    Code:
    for (int i=0; i<strlen(val); i++
    {
      int a=val[i]-48;
    La déclaration dans la boucle, pas terrible pour une optimisation...

    Code:
    SDL_Surface *ch = select(a, chiffres) ;
    C'est un programme sous UNIX ? Parce que select sous windows ça ne marche que sur les sockets...

    P.S. je ne suis pas certain que ce soit un problème de temps d'exécution qui fasse planter le programme (à moins qu'il soit exécuté sur un PC d'il y a 10 ans)...
    Dernière modification par bzh_nicolas ; 14/10/2011 à 20h45.

  17. #16
    Dlzlogic

    Re : Programme en C avec SDL plante très souvent !

    Bonjour bzh_Nicilas,
    Naturellement le code que j'ai écrit n'a pas été compilé.
    Par rapport au code d'origine je voulais seulement mettre en évidence certains points.
    Il est vrai que vous n'avez peut-être pas chargé ce code d'origine.
    Quand au problème de temps d'exécution, il est lié au plantage, puisque une opération très longue est faite dans une boucle indéfiniment, c'est à dire jusqu'au plantage.
    Par contre, je n'ai pas encore réussi à linker correctement la librairie SDL, donc pas d'essai possible.
    Mais si ce problème vous intéresse, charger le zip, par précaution, ne copiez que le source, cad n'exécutez pas le .exe.
    La librairie SDL est très facile à trouver et à charger.
    De mémoire select() est une fonction écrite dans le cadre de ce projet.

  18. #17
    doul11

    Re : Programme en C avec SDL plante très souvent !

    Bonjour,

    Citation Envoyé par Dlzlogic Voir le message
    Naturellement le code que j'ai écrit n'a pas été compilé.
    J'ai jamais posté un code sur le forum sans l'avoir compilé, on est ici pour aider par pour rajouter des bugs
    La logique est une méthode systématique d’arriver en confiance à la mauvaise conclusion.

  19. #18
    Dlzlogic

    Re : Programme en C avec SDL plante très souvent !

    Bonjour boul11
    Apparemment, vous n'avez pas suivi ce sujet.
    Il me semble qu'il y a une différence considérable entre un programme non compilé et un programme bugé.
    Je ne pouvais pas le compiler pour la simple raison que je n'avais pas les fichiers d'entête.
    Un bug, c'est beaucoup plus grave, le source se compile, le link se fait, l'exécution se passe à peu près bien ... jusqu'à atteindre le bug. Et à cette étape, je n'ai pas l'impression que vous ayez eu l'occasion d'en faire l'expérience.
    PS pour ce genre d'échange, les organisateurs du forum ont prévu les MP.

  20. #19
    bzh_nicolas

    Re : Programme en C avec SDL plante très souvent !

    Comme je le pensais, les plantages ne sont pas dû à un problème d'optimisation. Déjà je ne comprends pas que tu parviennes à exécuter quoi que soit. J'ai un plantage direct avec access violation...

    La liste des erreurs (valable pour le programme de AmigaOS et la modif de Dzlogic) :
    Attention, celà ne va pas faire fonctionner ton programme car chez moi il affiche une fenêtre, et ensuite il ne fait absolument rien...

    Première grosse remarque :
    Les fonctions de la lib SDL retourne des codes d'erreurs, ça n'est pas pour rien, il faut au moins faire en sorte de quitter l'appli proprement si quelque chose se passe mal, en plus ça permet de savoir où il y a un problème.
    Code:
    a = b / 100000 ;
    b est un int, tu le divises et obtiens donc un float inférieur à 1 tant qu'il ne vaut pas plus de 100000. Ensuite tu affecte ça dans un autre int. d'où perte d'info. a vaudra toujours 0 tant que tu n'auras pas cliquer plus de 100000 fois, ensuite il vaudra 1 tant que tu n'aura pas cliquer 200000, etc...

    Code:
    *ch = select(a, chiffres) ;
    C'est là que j'ai mon access violation, c'est logique d'ailleurs...
    Déjà ch est un pointeur sur une structure, on assigne pas une structure en faisant un simple =.
    Il faut l'assigner champ par champ, faire un memcpy (dans ces 2 cas l'espace mémoire de la structure doit déjà avoir été alloué) ou affecter un pointeur. Quelque chose du style :
    Code:
    ma_structure* maStruct = NULL;
    maStruct = &structure_deja_initialise; // attention structure_deja_initialise est une structure pas un pointeur sur une structure sinon, il faut faire maStruct = structure_deja_initialise;
    De plus à ce moment tu n'as pas encore initialisé ta variable ch elle pointe sur NULL.
    Tu essayes donc d'écrire à un endroit où tu n'as pas le droit de le faire.

    Code:
    SDL_Surface select (int a, SDL_Surface *chiffres)
    {
        SDL_Surface *ch = NULL ;
        ch = SDL_CreateRGBSurface (SDL_SWSURFACE, 8, 13, 32, 0, 0, 0, 0) ;
        SDL_Rect pos_chiffres ;
        switch (a)
        {
            pos_chiffres.y = 0 ; // cette ligne ne va jamais être exécuté, il faut la remonter en dehors du switch
            case 0 : pos_chiffres.x = 0 ; break ;
            case 1 : pos_chiffres.x = 8 ; break ;
            case 2 : pos_chiffres.x = 16 ; break ;
            case 3 : pos_chiffres.x = 24 ; break ;
            case 4 : pos_chiffres.x = 32 ; break ;
            case 5 : pos_chiffres.x = 40 ; break ;
            case 6 : pos_chiffres.x = 48 ; break ;
            case 7 : pos_chiffres.x = 56 ; break ;
            case 8 : pos_chiffres.x = 64 ; break ;
            case 9 : pos_chiffres.x = 80 ; break ;
        }
        SDL_BlitSurface (chiffres, NULL, ch, &pos_chiffres) ;
        return *ch ;
    // gros problème sur la ligne au dessus
    // tu retournes la valeur de la structure (ce qui ne veut pas dire grand chose quand on parle d'une structure) ce n'est pas un type de base, ça ne marche pas
    // autre gros problème : tu retourne ici la valeur d'une variable locale, ça ne fonctionne pas, la variable étant détruite lorsque tu quittes la fonction
    // sauf si la structure a été allouée dynamiquement (coup de bol ça semble être le cas avec SDL). As-tu vérifié ?
    }
    Il vaut mieux faire :
    Code:
    SDL_Surface* select (int a, SDL_Surface *chiffres)
    {
        SDL_Surface *ch = NULL ;
        ch = SDL_CreateRGBSurface (SDL_SWSURFACE, 8, 13, 32, 0, 0, 0, 0) ;
        SDL_Rect pos_chiffres ;
        pos_chiffres.y = 0 ;
        switch (a)
        {
        case 0 : pos_chiffres.x = 0 ; break ;
        case 1 : pos_chiffres.x = 8 ; break ;
        case 2 : pos_chiffres.x = 16 ; break ;
        case 3 : pos_chiffres.x = 24 ; break ;
        case 4 : pos_chiffres.x = 32 ; break ;
        case 5 : pos_chiffres.x = 40 ; break ;
        case 6 : pos_chiffres.x = 48 ; break ;
        case 7 : pos_chiffres.x = 56 ; break ;
        case 8 : pos_chiffres.x = 64 ; break ;
        case 9 : pos_chiffres.x = 80 ; break ;
        }
        SDL_BlitSurface (chiffres, NULL, ch, &pos_chiffres) ;
        return ch ;
    }
    // et au retour il faut faire :
    ch = select(a, chiffres) ;
    Code:
    SDL_Delay (30 - tp_a + tp_p) ;
    Tu as vérifié la valeur que te donne ton calcul ? Parce que là tu lui donnes un temps de pause négatif. Ce n'est même pas documenté dans SDL, pas la moindre idée de ce qui passe...

    Une fois ces erreurs corrigées, j'ai un programme stable mais qui n'a pas l'air de faire bien grand chose...
    Maintenant je pense (je suis sûre en fait) qu'il y a aussi un problème d'algo.

  21. #20
    Dlzlogic

    Re : Programme en C avec SDL plante très souvent !

    Bonjour Nicolas,
    Nous sommes parfaitement d'accord, mais Amigo a du boulot, et il a mis en attente.
    Pour l'instant, je n'ai pas réussi à faire le link. Il faut dire que je travaille avec Borland Builder, et naturellement, utiliser une librairie graphique, c'est pas vraiment idéal. Théoriquement, il ne devrait pas y avoir de conflit entre C et C++, mais j'ai pas vraiment insisté.
    D'ailleurs, je n'ai pas vraiment compris l'intérêt de sdl, les fonctions de l'API Windows conviennent pour faire ce genre de chose. Enfin, c'est mon avis.
    Dernière modification par Dlzlogic ; 16/10/2011 à 18h43.

  22. #21
    bzh_nicolas

    Re : Programme en C avec SDL plante très souvent !

    Il n'y a pas a pas vraiment de conflit C-C++ mais si on fait une compile C stricte il y a pas mal de chose qui ne passe pas (C++ est beaucoup plus "coulant" sur la syntaxe que C) et il faut retoucher pas mal de lignes avant que ça ne compile.
    SDL est destiné à faire des jeux 2D. Si tu as déjà essayé de ne faire ne serait-ce qu'un casse brique (un pong ça passe...) en te contentant de l'API windows, l'intérêt de SDL doit te sauter aux yeux.

Discussions similaires

  1. Structurer un programme en C avec SDL
    Par AmigaOS dans le forum Programmation et langages, Algorithmique
    Réponses: 10
    Dernier message: 02/03/2011, 19h59
  2. Programme utilisant SDL sur cygwin
    Par invite498c56f7 dans le forum Logiciel - Software - Open Source
    Réponses: 0
    Dernier message: 09/02/2010, 19h45
  3. [Divers] Electricité - Mes ampoules claquent très souvent
    Par inviteb23b1446 dans le forum Dépannage
    Réponses: 14
    Dernier message: 22/04/2008, 11h08
  4. mon pc plante très souvent
    Par invite05016f11 dans le forum Matériel - Hardware
    Réponses: 31
    Dernier message: 19/12/2007, 21h22