Bonjour/Bonsoir tout le monde !
Voici mon problème : Je code un programme qui compare des images afin de trouver la correspondante dans la base de données. Seulement, après que l'utilisateur entre le chemin de l'image à comparer, le programme cesse de fonctionner, je ne sais pas pourquoi. Voici mes fichiers :
main.cpp : http://pastebin.com/h8KcPVwf
rechercheDicho.cpp : http://pastebin.com/SXtkydRz
obtenirPixel.cpp : http://pastebin.com/dnyZXy10
input.cpp : http://pastebin.com/TjrLfTpS
output.cpp : http://pastebin.com/k8nGi69n
J'comprends vraiment pas d'où ça vient, quelqu'un pour éclairer ma lanterne s'il vous plait ? Merci d'avance !
Tu serais pas en train d'essayer d’accéder aux pixels de surfaces inexistantes ?
Parce que même si ton tableau de SDL_Surface* fait 88 cases, il n'y en a que 7 d'initialisées. Ce qui fait que lorsque tu lances la rechercheDico(), tu appelle la fonction obtenirPixel() sur des SDL_Surface* non définie.
Sinon n'oublies pas de libérer les SDL_Surface* à la fin du programme, sinon il a fuite de mémoire.
Ah et aussi, dans main(), tu peux faire directement:
val = SDL_LoadBMP(cheminVal.c_str());
J'ai pas test et j'ai un peux regardé le code alors je te donne des pistes a vérifier:
Si NULL c'est que le chemin est mauvais ou erreur de la fonction sdl pour x ou y raison. Du coup dans la fonction suivante il vas lire dans val: NULL et ca prend une seule case mémoire. Or dans "dichotomie", tu cherche à accèder a des valeurs dont tu aura pas le droit -> segmentation fault -> programme plante
N'oublie pas de :
Bh justement nan sachant que quand j'entre un chemin dans la console, je fais en sorte que ce soit un déjà initialisé.
Merci quand même !
Merci déjà pour vos réponse mais j'ai le même problème pour un autre projet, ça fait depuis le début d'après-midi que je cherche, sans succès. J'arrive pas à comprendre, en gros dès que j'appelle la fonction bataille, le programme plante. Voici mes fonctions :
Bataille.cpp : http://pastebin.com/PwzUeVNj
Merci d'avance ! ![]()
Mais est-ce qu'il plante à l'appel de creerCarte ? (dans Bataille.cpp)
Alors j'ai enlever l'appel à cette fonction mais ça plante encore.. ![]()
Ca veut dire quoi concretement "le programme cesse de fonctionner," ?
Bh... Qu'il a planté ? ^^
Tu as bien initialiser la bibliothèque avant d'utiliser SDL_LoadBMP ?
Sinon tu doits initialiser ta libraire ainsi :
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
// fprint est utiliser uniquement a la place de std::cout afin de pouvoir
// lire correctement le message d'erreur retourner par SDL_GetError()
// fprintf provient de #include <cstdio>
std::fprintf(stdout, "SDL Initialisation failed - %s \n", SDL_GetError());
}
Le fait qu'une application plante, ca peut etre un million de chose. Est ce que c'est une division par zero, une erreur de segmentation, stack overflow, out of memory, un appel a exit?
En general, faire passer l'application dans valgrind aide. Mais peut etre que valgrind et la sdl ne vont pas tres bien ensemble.
Le 13 mars 2015 à 15:50:02 89ron a écrit :
Tu as bien initialiser la bibliothèque avant d'utiliser SDL_LoadBMP ?Sinon tu doits initialiser ta libraire ainsi :
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { // fprint est utiliser uniquement a la place de std::cout afin de pouvoir // lire correctement le message d'erreur retourner par SDL_GetError() // fprintf provient de #include <cstdio> std::fprintf(stdout, "SDL Initialisation failed - %s \n", SDL_GetError()); }
Oui, sinon j'aurais directement une erreur, là la fenêtre s'ouvre et fait d'autres trucs mais dès que je vais dans cette fonction le programme plante.
godrik
Bh il me semble qu'il n'y a rien de tous ça justement. ![]()
Dans ce cas test si ta fonction renvoi un pointeur NULL
ex :
if( SDL_LoadBMP("BDD/empreinte_001.bmp") == NULL )
{
std::fprintf(stdout, "SDL_LoadBMP - %s \n", SDL_GetError());
}
else
{
std::fprintf(stdout, "SDL_LoadBMP est OK \n");
}
SDL_GetError te donnera surement ton problème problème.
Arf, ce problème là est passé, regarde quelques postes au dessus. ![]()
Je te conseille d’exécuter ton jeu dans Visual Studio Express en mode Depug (pas Release), il pointera automatiquement sur la ligne qui pose problème.
Parce-que là il manque pas mal de fichier pour t'aider.
PS: Tu utilises quel tuto pour la SDL ?
Bh j'utilise déjà un Debugger mais ça me signale rien.
J'utilise plus de tutos,mais avant j'utilisais le tuto du siteduzero (OpenClassrooms maintenant.).
EDIT: Au cas où, mon IDE est Code::Blocks avec en compilateur mingw.
Bon, j'ai reprogrammé tout le fichier (mis à part la fonction distribuerCarte, voici ce que ça donne :
#include <SDL/SDL.h>
#include "bataille.h"
#include "Boss.h"
#include "data.h"
#include "rand_a_b.h"
#include "Barbare.h"
#include "Magicien.h"
#include "Sorcier.h"
#include "Druide.h"
#include "Debutant.h"
void bataille(SDL_Surface* ecran)
{
SDL_Surface *fond(SDL_LoadBMP("GRAPHISMES/BATAILLE/champ.bmp"));
SDL_Rect pos;
SDL_Event event;
int nbBarbare(getBarbare()), nbMagicien(getMagicien()), nbSorcier(getSorcier()), nbDruide(getDruide()), nbDebutant(getDebutant());
int nbCartes(nbBarbare+nbMagicien+nbSorcier+nbDruide+nbDebutant);
int deckJ1[nbCartes], deckIA[nbCartes], i(0);
bool continuer(true);
Boss j1(500, SDL_LoadBMP("GRAPHISMES/CARTES/BOSS/boss.bmp")), ia(500, SDL_LoadBMP("GRAPHISMES/CARTES/BOSS/boss2.bmp"));
Carte cJ1[nbCartes], cIA[nbCartes];
pos.x = 0;
pos.y = 0;
for(i = 0; i < nbCartes; i++)
deckJ1[i] = distribuerCarte(nbBarbare, nbMagicien, nbSorcier, nbDruide, nbDebutant);
/* ***** PLANTE *****
for(i = 0; i < nbCartes; i++)
cJ1[i] = creerCarte(deckJ1, i);
***** PLANTE ***** */
while(continuer)
{
SDL_PollEvent(&event);
switch(event.type)
{
case SDL_QUIT:
exit(EXIT_SUCCESS);
break;
case SDL_KEYDOWN:
if(event.key.keysym.sym == SDLK_ESCAPE)
continuer = false;
break;
}
SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));
SDL_BlitSurface(fond, NULL, ecran, &pos);
j1.afficher(ecran, 559, 396);
ia.afficher(ecran, 559, 205);
SDL_Flip(ecran);
}
}
int distribuerCarte(int nbBarbare, int nbMagicien, int nbSorcier, int nbDruide, int nbDebutant)
{
int carte;
while(!carte)
{
carte = rand_a_b(1, 5);
if(!nbBarbare)
{
if(carte == 1)
carte--;
}
if(!nbMagicien)
{
if(carte == 2)
carte = 0;
}
if(!nbSorcier)
{
if(carte == 3)
carte = 0;
}
if(!nbDruide)
{
if(carte == 4)
carte = 0;
}
if(!nbDebutant)
{
if(carte == 5)
carte = 0;
}
}
return carte;
}
Carte creerCarte(int deck[], int x)
{
Barbare barbare;
Magicien magicien;
Sorcier sorcier;
Druide druide;
Debutant debutant;
switch(deck[x])
{
case 1:
return barbare;
break;
case 2:
return magicien;
break;
case 3:
return sorcier;
break;
case 4:
return druide;
break;
case 5:
return debutant;
break;
}
}
Comme vous avez pu le voir, j'ai remarquer où ça plante : à l'appel de la fonction creerCarte, mais bon, je vois toujours pas pourquoi. ![]()
Peux-tu nous détailler ta Class Carte ?
Sinon ton switch dans la methode creeCarte est mauvais. (faut éviter de mettre plusieurs return, c'est chiant a debug, une fonction / une methode = une sortie.)
Les class Barbare, Magicien, Sorcier, Druide et Debutant sont elle des class dérivée de Carte ? Parceque ta fonction creeCarte s'attend a retourner des objets Cartes et non des objets Barbares, etc.
Ta méthode distribuerCarte a une variable non initialise : int carte; du coup ton while (!carte) est initialiser avec une valeur aléatoire très grandes,
PS: Sinon je voudrais pas te décourager mais évite Openclassroom a l'avenir car ton code dans l'ensemble ressemble plus a du "C with Class" que du vrai C++.
Carte.h :
#include <iostream>
#include "Boss.h"
class Carte
{
public:
Carte();
Carte(int vie, int level, int attaque, int defense, SDL_Surface *image);
void attaquer(Carte &cible);
void attaquerBoss(Boss &cible);
void recevoirDegats(int degats);
void initPos(int x, int y);
void deplacer();
void afficher(SDL_Surface* ecran, int x, int y);
SDL_Surface *getImage();
SDL_Rect &getPos();
protected:
int m_vie;
int m_attaque;
int m_defense;
int m_level;
int m_x;
int m_y;
std::string m_race;
SDL_Surface *m_image;
SDL_Rect m_pos;
};
#endif // CARTE_H_INCLUDED
Carte.cpp :
#include <SDL/SDL.h>
#include "Carte.h"
using namespace std;
Carte::Carte()
{
}
Carte::Carte(int vie, int level, int attaque, int defense, SDL_Surface *image) : m_vie(vie), m_level(level), m_attaque(attaque), m_defense(defense), m_image(image)
{
}
void Carte::attaquer(Carte &cible)
{
cible.recevoirDegats((1 - m_defense / 100) * m_attaque);
}
void attaquerBoss(Boss &cible)
{
cible.recevoirDegats(1);
}
void Carte::recevoirDegats(int degats)
{
m_vie -= degats;
if(m_vie < 100)
m_vie = 0;
}
void Carte::initPos(int x, int y)
{
m_pos.x = x;
m_pos.y = y;
}
void Carte::deplacer()
{
// A FAIRE
}
void Carte::afficher(SDL_Surface* ecran, int x, int y)
{
initPos(x, y);
SDL_BlitSurface(m_image, NULL, ecran, &m_pos);
}
SDL_Surface *Carte::getImage()
{
SDL_SetColorKey(m_image, SDL_SRCCOLORKEY, SDL_MapRGB(m_image->format, 255, 255, 0));
return m_image;
}
SDL_Rect &Carte::getPos()
{
return m_pos;
}
Comment ça mauvais ? Il vaut mieux que je mette une tonne de if ?
Oui, elles sont héritées de la classe Carte !
Oui, mais après elle est initialisée avec la fonction rand_a_b.
Qu'entends-tu par C with class ?
Comment ça mauvais ? Il vaut mieux que je mette une tonne de if ?
non essai plutôt ça :
Carte carte;
switch(deck[x])
{
case 1:
carte = static_cast<carte>(barbare);
break;
case 2:
carte = static_cast<carte>(magicien);
break;
// etc.
}
return carte;
}
Oui, elles sont héritées de la classe Carte !
Oui, mais après elle est initialisée avec la fonction rand_a_b.
Qu'entends-tu par C with class ?
- Une procédure Bataille qui appelle un header bataille -> c'est du C
- Initialiser des variables avant l’exécution de multiples procédure dans une boucle principale c'est du C.
- Utiliser des Classes avec des méthodes uniquement public, -> c'est du C with Class.
- Utiliser des tabeaux [ ] -> c'est du C
- Utiliser des int pour délimiter des la taille du tableaux -> c'est du C.
Dans ton main initialiser des tableaux de cette manière, est suicidaire :
SDL_Surface *tab[88] =
{SDL_LoadBMP("BDD/empreinte_001.bmp"), SDL_LoadBMP("BDD/empreinte_002.bmp")}
Que fait tu si le fichier empreinte_002.bmp est pas trouver par SDL_LoadBMP ? Tu verifies pas s'il y a une erreur, du coup SDL_LoadBMP peux retourner un pointeur NULL qui fera planter ton application, quand le tableau sera parcouru.
Au lieu d'utiliser les tableau du C, préfère les Vectors, qu lieu d'utiliser des tableau de Class, utilise des objets, ex:
au lieu de :
int deckJ1[nbCartes], deckIA[nbCartes];préfère :
Deck deckJoueur ( /*nbCartes*/ 7 , /*nom du deck*/ "joueur" );
Deck deckJoueur ( /*nbCartes*/ 8 , /*nom du deck*/ "ia" );
N'utilise pas de boucle for pour remplir tes decks, c'est a ta class Deck de les remplir.
Revoi l'utilisation des pointeur ou des références, parce-que tes objet en sortie de fonctions sont retourner souvent par copie et non par référence ou par pointeur.
Tes classes doivent avoir aussi des méthodes privées.
Ton main doit être mieux organiser, il devrait plus ressembler a ceci :
#include <cstdio>
#include <SDL.h>
#include "Debug.h"
#include "Game.h"
const int width = 640;
const int height = 480;
const Uint32 fps = 60;
const Uint32 delay_time = (Uint32)(1000.f / fps);
int main(int argc, char* args[])
{
Uint32 frameStart, frameTime;
int error = 0;
std::cout << "game init attempt...\n";
//Initialisation du jeu et de la SDL
//doit se faire dans une classe Game
if (TheGame::Instance()->init("game1", width, height))
{
frameStart = SDL_GetTicks();
// Main loop
while (TheGame::Instance()->running())
{
// Recuperation des evenements Claviers/Mannette/Souris
TheGame::Instance()->handleEvents();
// Mise a jour des Objets
TheGame::Instance()->update();
// Affichage des objets
TheGame::Instance()->render();
// Verification des images par secondes
frameTime = SDL_GetTicks() - frameStart;
if (frameTime < delay_time)
{
// Permet de soulager le processeur
SDL_Delay(delay_time - frameTime);
}
}
}
else
{
std::fprintf(stdout, "Game init failure - %s \n", SDL_GetError());
error = -1;
}
// SDL quit
std::cout << "game closing... \n";
// Netoie la memoire des differentes allocation dynamiques
TheGame::Instance()->clean();
PAUSE; // system("pause");
return error;
}