Je rencontre un problème dans le code d'un logiciel fait avec SFML, j'essaie de créer une classe Button qui contient la forme du bouton (RectangleShape) et son texte (Text).
Le problème apparait quand j'exécute le programme en mode debug, la console m'affiche : "Exception non gérée à 0x00007FFBB03469E9 (sfml-graphics-d-2.dll) dans Vokey.exe : 0xC0000005 : Violation d'accès lors de la lecture de l'emplacement 0xFFFFFFFFFFFFFFFF."
Ces variables sont initialisées dans les .hpp que je n'ai pas inclus, je pense que ce n'est pas nécessaire, je peux vous les partager si besoin mais j'ais simplement fais :
Ce que veux dire bacelar, je pense c'est de compiler en mode Debug (donc avec l'option qui permet de produire les symboles de débuggage) puis de lancer l' exécutable ainsi généré avec le Debugger (clic droit sur le projet de l'exécutable, choisir 'déboguer' puis 'démarrer une nouvelle 'instance' ). Avec un debugger, tu as la possibilité d' exécuter en mode pas à pas ton programme et également de mettre des 'breakpoints' qui vont dire au debugger de s'arrêter à ce 'breakpoint' à ce moment là tu pourras surveiller la valeur actuelle des différentes variables qui sont dans la portée de la fonction.
Ce que veux dire bacelar, je pense c'est de compiler en mode Debug (donc avec l'option qui permet de produire les symboles de débuggage) puis de lancer l' exécutable ainsi généré avec le Debugger (clic droit sur le projet de l'exécutable, choisir 'déboguer' puis 'démarrer une nouvelle 'instance' ). Avec un debugger, tu as la possibilité d' exécuter en mode pas à pas ton programme et également de mettre des 'breakpoints' qui vont dire au debugger de s'arrêter à ce 'breakpoint' à ce moment là tu pourras surveiller la valeur actuelle des différentes variables qui sont dans la portée de la fonction.
J'utilisais donc déjà cette option par contre je ne connaissais pas les breakpoint c'est génial merci ! Par contre je ne trouve quand même pas la solution
rouIoude a écrit:
Je n'utilise pas cette lib, mais :
Un main.hpp je ne suis pas pour, le module qui contient la fonction main, n'est pas voué à être réutilisé.
Les définitions de variables serait mieux placées dans les fichiers sources .cpp , les fichiers entêtes .hpp sont plutôt voués aux déclarations.
Et aussi éviter autant que possible les variables globales.
Ok donc j'ai supprimé mon main.hpp et à l'avenir j'essaie d'éviter les variables globales, merci du conseil
- Edité par CédricL'Informaticien 21 juin 2023 à 13:26:33
Petite précision à l'intervention de @Warren79, pas besoin de compiler en Mode Debug pour pouvoir déboguer, on peut générer des informations de debugging même en Release, même si c'est moins précis et plus compliqué à suivre.
Je suis tout à fait d'accord avec @rouloude, pas de code dans les .hpp.
Potentiellement inclus plusieurs fois, on ne sait pas si les différentes "instances" des variables globales seront fusionnées ou pas, on ne sait pas dans quel ordre ce foutoir global s'initialise, etc...
Qu'est qui garantit que votre variable globale "window" est initialisée quand Button::draw de votre variable globale "button" est appelé ?
Rien, si elles ne sont pas défini dans la même unité de compilation. (et bonjour la galère quand ces cochonneries sont dans des .cpp différents et encore pire quand c'est dans des .h)
- Edité par bacelar 21 juin 2023 à 18:03:02
Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
Bacelar a écrit [... Release et mode Debug à la fois ]
Je le savais déjà , cela fait partie des options de génération de projets dans CMake sous l'appelation 'RelWithDebInfo', logiciel que j'utilise depuis pas mal d'années mais comme je n'utilise ce mode de génération que très peu je n' y avais plus pensé. Je développe principalement sous xubuntu avec codelite, gcc et CMake mais parfois je teste aussi d'autres plateformes avec CMake comme Windows avec visual Studio ou mingw en ligne de commande avec des fichiers batchs.
J'avais utilisé le profiler de Visual Studio une fois pour tester un programme de jeu vidéo que j'avais créé en C++ pour savoir dans quels fonctions mon programme passait le plus de temps, cela m'avait permis de déceler une fonction qui n' était pas nécessairement utile à chaque tour de boucle de ma fonction update() une fois le jeu en mode partie et j'avais vu également que la fonction la plus utilisée dans une partie par le joueur était celle qui testait si un délai impartit s' était écoulé.
ça sent la ligne 16 du button.cpp qui saute lors du push_back
la texture est perdue et il tape à son ancien emplacement alors qu'il n'a plus le droit d'y accéder
Alors comment je peux le vérifier et le corriger ? C'est bien pour ça que que la variable font est déclarée comme private pour éviter qu'elle ne perde sa valeur attribuée ? Et qu'est ce que tu entend par "la ligne 16 saute lors du push_back"
Faire du profiling en Debug, ça n'a pas beaucoup de sens. ;-)
Disons, que comme je ne fais que des jeux indépendants / amateurs, si ça rame à un moment donné dans un de mes jeux c'est plus le code que je produis qui serait fautif de ce ralentissement. Ma config: AMD Ryzen 3700X et Nvidia RTX 2700. D' autant plus que la SDL2 a des fonctions de dessinage/drawing assez performantes comme la SFML 2. C'est pour cette raison que je ne lance pas souvent le profiler sous Visual Studio. Par contre à chaque fois que j' implémente une nouvelle fonctionnalité dans un de mes programmes je le teste systématiquement en mode Debug.
@Djarkan : L'objet font ne me semble pas créé dans le constructeur de la classe Button. (On ne sais pas où il est crée, mais il n'est pas local au constructeur de la classe Button).
Comme j'ai dit plus haut, je n'utilise pas cette lib, mais il n'y a aucune raison que l'objet font soit modifié (que la police de caractère soit déchargée) à la sortie du constructeur de la classe Button.
Ce qui est détruit à la sortie d'un bloc ce sont les variables locales au bloc (variables automatiques). Or ici ce n'est pas le cas.
Comme j'ai dit plus haut, je n'utilise pas cette lib, mais il n'y a aucune raison que l'objet font soit modifié (que la police de caractère soit déchargée) à la sortie du constructeur de la classe Button.
Ce qui est détruit à la sortie d'un bloc ce sont les variables locales au bloc (variables automatiques). Or ici ce n'est pas le cas.
C'est ce qui me semble aussi ! La variable font est déclarée dans le Button.hpp c'est une variable private comme dit plus haut, elle ne devrait pas perdre sa valeur puisqu'elle est initialisée dans le constructeur
Button.hpp
#include <SFML/Graphics.hpp>
#include <iostream>
using namespace std;
using namespace sf;
#define BUTTON_COLOR Color(217, 217, 217)
#define TEXT_COLOR Color(255, 255, 255)
class Button
{
public:
Button(string btn_txt, int chr_size, Vector2f size);
void update(RenderWindow& window);
void setPosition(Vector2f pos);
void draw(RenderWindow& window);
void startClickAnimation();
//GETS
Vector2f getPosition();
FloatRect getGlobalBounds();
private:
RectangleShape button;
Font font;
Text text;
Clock time;
bool start_animation;
float scale_speed;
};
j ai une classe bitmaptext qui contient une classe bitmapfont
le constructeur de bitmaptext appele le constructeur de bitmapfont
je passe soit le nom de la fonte ou l'adresse le la font
BitmapText(std::string fontName, unsigned int glyphWidth, unsigned int glyphHigth);
BitmapText(sf::Texture& fontTexture, unsigned int glyphWidth, unsigned int glyphHigth);
BitmapText::BitmapText(std::string fontName, unsigned int glyphWidth, unsigned int glyphHigth) : m_bitmapFont(fontName, glyphWidth, glyphHigth),
m_fontName{fontName}, m_glyphWidth{glyphWidth},
m_glyphHigth{glyphHigth}, m_scale{1}
{
}
BitmapText::BitmapText(sf::Texture& fontTexture, unsigned int glyphWidth, unsigned int glyphHigth) : m_bitmapFont(fontTexture, glyphWidth, glyphHigth),
m_glyphWidth{glyphWidth}, m_glyphHigth{glyphHigth}, m_scale{1}
{
}
BitmapFont(std::string fileName, unsigned int glyphWidth, unsigned int glyphHigth);
BitmapFont(sf::Texture& fontTexture, unsigned int glyphWidth, unsigned int glyphHigth);
BitmapFont::BitmapFont(std::string fileName, unsigned int glyphWidth, unsigned int glyphHeigth) : m_glyphWidth{glyphWidth}, m_glyphHeigth{glyphHeigth}
{
setBitmapFont(fileName);
}
BitmapFont::BitmapFont(sf::Texture& fontTexture, unsigned int glyphWidth, unsigned int glyphHeigth) : m_letterTexture{fontTexture}, m_glyphWidth{glyphWidth}, m_glyphHeigth{glyphHeigth}
{
m_letterSprite.setTexture(fontTexture);
sf::Vector2u textSize = m_letterTexture.getSize();
m_nbColunms = textSize.x / m_glyphHeigth;
}
bool BitmapFont::setBitmapFont(std::string fileName)
{
bool success = m_letterTexture.loadFromFile(fileName);
if(success) { m_letterSprite.setTexture(m_letterTexture); }
sf::Vector2u textSize = m_letterTexture.getSize();
m_nbColunms = textSize.x / m_glyphHeigth;
return success;
}
tant je je l'utilise "à la volée" cela fonctionne, des que je la met dans un container push_back ou std::make_unique ... badaboum j'ai aussi un crash violation d'acces
donc cedric est ce que sans le mettre dans un vecteur , ton bouton fonctionne ??
avant d'en faire plein, est ce qu'il fonctionne seul ?
Chaque fois qu'un bouton est instancié, une font est instanciée et chargée, donc accès au disque. C'est très dommage, d'autant que la plupart du temps, les boutons d'une interface graphique utilisent la même font. A mon avis, il sera plus judicieux d'externaliser les fonts, et faire en sorte que le bouton "utilise" une font.
donc cedric est ce que sans le mettre dans un vecteur , ton bouton fonctionne ??
avant d'en faire plein, est ce qu'il fonctionne seul ?
- Edité par Djarkan 24 juin 2023 à 11:59:15
Non, même seul le problème reste le même
Deedolith a écrit:
Question: Un bouton doit-il "posséder" une font ?
Chaque fois qu'un bouton est instancié, une font est instanciée et chargée, donc accès au disque. C'est très dommage, d'autant que la plupart du temps, les boutons d'une interface graphique utilisent la même font. A mon avis, il sera plus judicieux d'externaliser les fonts, et faire en sorte que le bouton "utilise" une font.
C'est vrais vous avez raison, par contre même en créant la font depuis le main.cpp et en la passant en paramètre au constructeur le problème apparait toujours.
J'ai réussi à le faire fonctionner avec une méthode pas du tout efficace : J'ai crée une fonction update qui crée une font et l'applique au texte avant de le dessiner à chaque répétition de ma boucle principale. Cela "règle" le soucis mais ce n'est pas du tout optimisé
if (!font.loadFromFile("src/JosefinSans-Bold.ttf"))
{
cout << "Erreur chargement de la Font" << endl;
}
text.setFont(font);
tu as une console pour voir les erreurs ? parce que si tu as un échec au chargement du fichier font tu continues quand même.
Tu pourrais peut-être utiliser les exceptions pour gérer ça ?
...
SFML - Classe Button, message d'erreur
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Mon site web de jeux SDL2 entre autres : https://www.ant01.fr
Mon site web de jeux SDL2 entre autres : https://www.ant01.fr
Mon site web de jeux SDL2 entre autres : https://www.ant01.fr