Répondre à la discussion
Affichage des résultats 1 à 20 sur 20

c++ : appeler une fonction d'une classe dérivée




  1. #1
    destroyedlolo

    Unhappy c++ : appeler une fonction d'une classe dérivée

    Bonjour,

    J'ai une classe définie comme suit :

    Code:
    class Context : virtual public Network, virtual public Porte, virtual public MQTTcon {
     ...
    public:
    	void save( void ){
    		this->crc = this->crc32();
    		ESP.rtcUserMemoryWrite(0, (uint32_t*)this, sizeof(*this));
    	}
    ...
    };
    Dans les classes dont elles dérivent, j'ai le besoin d'appeler le save() de Context.

    J'ai donc fait
    Code:
    class Network {
    ...
    protected:
    	virtual void save( void ) = 0;
    ...
    	enum NetworkMode connect( void ){
    ... bla bla bla ...
    		this->status();
    		this->save();
    	}
    };
    Et là, c'est le drame : "Load or store to an unaligned address"
    Si je commente le this->save(); plus de crash ...
    Je m'y prend donc mal : quelle serait la solution ?

    Merci

    -----


  2. Publicité
  3. #2
    Jack

    Re : c++ : appeler une fonction d'une classe dérivée

    Dans la classe Network, la fonction save est virtuelle pure, donc Network est une classe abstraite.
    Du coup, this->save(); n'a pas de sens puisque save n'est pas définie. Et this non plus n'a pas de sens puisque la classe n'est pas instanciable.

    A+

  4. #3
    destroyedlolo

    Re : c++ : appeler une fonction d'une classe dérivée

    Citation Envoyé par Jack Voir le message
    Dans la classe Network, la fonction save est virtuelle pure, donc Network est une classe abstraite.
    Du coup, this->save(); n'a pas de sens puisque save n'est pas définie.
    Ben du coup, comment puis-je appelé le save() de la classe qui hérite de Network ?
    En fait, toutes ces classes définissent des variables qui sont ensuite sauvées dans la mémoire RTC du bignou : mais comme toutes ces classes peuvent modifier leurs propres variable (a quel réseau somme nous connecté, situation de la porte, ...) j'ai donc besoin de pouvoir faire cette sauvegarde a plusieurs endroits.

    Citation Envoyé par Jack Voir le message
    Et this non plus n'a pas de sens puisque la classe n'est pas instanciable.
    Hum, dans ce cas, pourquoi Gcc ne fait pas d'erreur ? (j'ai mis -wall)
    Mon attention, c'est que le this corresponde à la classe Context, donc une fois l'héritage accomplis.


  5. #4
    pm42

    Re : c++ : appeler une fonction d'une classe dérivée

    A vérifier mais je pense que ton code est correct du point de vue C++ mais que ton crash vient de la ligne :

    Code:
    ESP.rtcUserMemoryWrite(0, (uint32_t*)this, sizeof(*this));
    auquel tu passes des arguments qui ne respectent pas les contraintes d'alignement ou un truc dans le genre.
    Voir par ex https://github.com/esp8266/Arduino/issues/3365

  6. #5
    destroyedlolo

    Re : c++ : appeler une fonction d'une classe dérivée

    Ben j'étais tombé sur ce ticket lors de mes recherches avant de faire la demande ici ... mais ca plante aussi si ma fonction save() est vide
    Je pense donc que Jack a raison et que je ne peux peut-être pas construire mes objets comme ça.
    Je le fais en Lua où les objets sont vraiment créé dynamiquement, mais, à la réflexion, le C++ étant compilé, j'imagine qu'il doit savoir au moment de la compilation à quoi l'objet doit ressembler.

    Mais bon, je suis peut-être dans le faux donc si quelqu'un a une meilleur idée ...

  7. A voir en vidéo sur Futura
  8. #6
    pm42

    Re : c++ : appeler une fonction d'une classe dérivée

    Tu essaies le code suivant qui est dérivé du tien :

    Code:
    #include <iostream>
    
    class Network {
    public:
        virtual void save( void ) = 0;
        void connect( void ){
            this->save();
        }
    };
    
    class Context : virtual public Network {
    public:
        void save( void ){
            std::cout << "in Context:save" << std::endl;
        }
    };
    
    int main(int argc, char** argv) {
            Context c;
            c.connect();
    }
    Et on crée bien la classe Context dans le main, on appelle connect défini dans Network dessus qui elle même appelle save.
    Et naturellement, on appelle le save de Context.

    Si on n'avait pas ce genre de comportement, les méthodes virtuelles et classes abstraites ne serviraient pas à grand chose.
    Donc ton problème est ailleurs à mon avis.

  9. #7
    Jack

    Re : c++ : appeler une fonction d'une classe dérivée

    Citation Envoyé par pm42 Voir le message
    Donc ton problème est ailleurs à mon avis.
    Tu as sûrement raison.

    L'erreur semble donc indiquer une erreur d'alignement mémoire dû à une taille de bloc non adaptée lors de l'écriture. Ca a l'air très spécifique à l'implantation mémoire du système sur lequel tu travailles, un arduino à priori. C'est un problème récurrent semble-t-il: https://github.com/esp8266/Arduino/issues/2875

  10. Publicité
  11. #8
    destroyedlolo

    Re : c++ : appeler une fonction d'une classe dérivée

    Le code complet se trouve sur mon github si vous voulez voir (c'est loin d'etre fini) et c'est en effet pour un ESP8266 qui peut se programmer comme un Arduino.
    Pour économiser la batterie , je le met en mode DeepSleep au bout duquel il reboote et perd donc tous les contenu de sa mémoire ... sauf une petite zone nommée RTC. Le but de mon binse est d'y conserver certaines infos du contexte (sur quel réseau nous sommes connecté, position de la porte, consigne venant de la domotique, ...).
    Pour se faire, j'ai défini plusieurs classes en fonction du "domaine" (réseau, porte, ...) dont le contexte hérite : tous les champs seront sauvegardés dans la RTC. J'ai fait des tests simple et ca fonctionne : je n'ai bien que les champs dans le RTC, mais il n'y a que depuis que j'ai des save() dans les classes parentes que ca ne fonctionnent plus.

    Vu que pm42 nous dit, code à l’appui, que ce genre d'appel devrait fonctionner, je suis vraiment démuni. Je ne suis pas sur non plus que ca vienne de l'alignement des données elles-même vu que ca plante aussi avec un save() vide, peut etre plus un pb de pointeur sur les fonctions
    Après, l'ESP fonctionne suivant l'architecture Harvard donc le compilo fait peut-être un méli mélo a ce niveau ... mais pourquoi ?
    Je ferai le tests avec le code simple de pm42 ce soir pour voir si le pb vient de la.
    Dernière modification par destroyedlolo ; 19/12/2017 à 11h36.

  12. #9
    destroyedlolo

    Re : c++ : appeler une fonction d'une classe dérivée

    Bonsoir,

    Voila ce que j'ai essayé sur l'ESP :

    Code:
    void setup() {
      // put your setup code here, to run once:
    	Serial.begin(115200);
    	delay(100);
    }
    
    class Network {
    public:
        virtual void save( void ) = 0;
        void connect( void ){
    			Serial.println("N1");
          this->save();
        }
    };
    
    class Network2 {
    public:
        virtual void save( void ) = 0;
        void connect2( void ){
    			Serial.println("N2");
          this->save();
        }
    };
    
    class Context : public Network, public Network2 {
    public:
        void save( void ){
        	Serial.println("Save");
        }
    };
    
    void loop() {
    	Context c;
    	c.connect();
    	c.connect2();
    
    	ESP.deepSleep( 20e3 );
    }
    Évidemment, ca ne plante pas ... Je vais donc rajouter petit bout par petit bout mon code jusqu'a ce que ca crash ...

  13. #10
    Merlin95

    Re : c++ : appeler une fonction d'une classe dérivée

    La seule ligne différente est :

    Code:
    class Context : virtual public Network {
    vs

    Code:
    class Context : public Network {

  14. #11
    destroyedlolo

    Re : c++ : appeler une fonction d'une classe dérivée

    Oui, c'est parce que ca plante dans les 2 cas. Mes essais actuels sont sans le virtual.

  15. #12
    ID123

    Re : c++ : appeler une fonction d'une classe dérivée

    Tu n'as pas donné, dans ton code d'origine (-message #1), les lignes de code de création de l'objet. On est d'accord, c'est bien un objet Context que tu crées ?
    Autre piste : vu le message d'erreur, utiliser dans gcc une option "forte" d'alignement des données. par exemple sur deux mots.

  16. #13
    Jack

    Re : c++ : appeler une fonction d'une classe dérivée

    Citation Envoyé par destroyedlolo Voir le message
    Oui, c'est parce que ca plante dans les 2 cas. Mes essais actuels sont sans le virtual.
    Vu l'héritage multiple, il faudra sûrement remettre virtual une fois le problème résolu.

  17. #14
    destroyedlolo

    [Trouvé] c++ : appeler une fonction d'une classe dérivée

    Bon, j'ai trouvé !!!

    Dans mes sous-classes, j'ai mis les variables que je veux sauvegarder.
    Donc en simplifiant, ca donnerait un truc du genre

    Code:
    class Network {
    	int réseau;
    
    protected:
    	virtual void save( void ) = 0;
    ...
    	enum NetworkMode connect( void ){
    ... bla bla bla ...
    		this->status();
    		this->save();
    	}
    };
    Ensuite, j'ai compiler un truc sur mon PC pour m'assurer que "this" pointe bien sur mes données et que sizeof(*this) à bien la taille de mes données.
    Sauf que, sauf que ... ben ça a marcher sur le PC, mais sur l'ESP
    Code:
    ESP.rtcUserMemoryRead(0, (uint32_t*)this, sizeof(*this))
    corrompe visiblement les pointeurs vers les méthodes et ... bbbbbboooommmm !

    Evidemment, c'était parfaitement capilotracté comme code, mais mes tests sur le PC ayant fonctionné, je me suis dit que ca serait plus élégant que de créer une structure dédiée aux données ce qui me pose le probleme de concaténer les données après dans la mémoire ...
    Mais je ne vais pas y couper

    Bref, faut que je redesigne mon truc
    Dernière modification par destroyedlolo ; 20/12/2017 à 17h07.

  18. #15
    destroyedlolo

    Re : [Trouvé] c++ : appeler une fonction d'une classe dérivée

    Bon ben voila, c'est corrigé.

    Bonnes fetes.

  19. #16
    Jack

    Re : [Trouvé] c++ : appeler une fonction d'une classe dérivée

    Bonnes fêtes à toi également.

    Qu'est-ce que tu utilises comme framework pour développer en C++ sur l'ESP8266?

  20. #17
    destroyedlolo

    Re : [Trouvé] c++ : appeler une fonction d'une classe dérivée

    Citation Envoyé par Jack Voir le message
    Qu'est-ce que tu utilises comme framework pour développer en C++ sur l'ESP8266?
    Et bien, pour les dev, tu as le choix entre :
    • Utiliser l'IDE Arduino classique (IDE java qui ensuite lance son propre Gcc)
    • Utiliser une chaine classique à base de MakeFile avec des scripts qui te facilite le travail.
    • il me semble aussi qu'il est possible de passer par Eclipse mais je n'ai pas testé

    Même si je ne suis pas trop IDE (d'habitude, je développe directement avec VIM et des autogénérateurs de MakeFile), j'ai quand même choisie de passer par cette dernière car elle facilite grandement l'inclusion des librairies tierces. Par contre, il est possible d'utiliser un éditeur externe et j'ai craqué rapidement : l'IDE me sert à la compilation mais l'éditeur reste VIM

    Si tu parles de framework côté code, tu peux réutiliser quasiment tous l'écosystem de l'arduino qui est particulièrement riche. Le problème est que ce n'est qu'une collection de librairies hétéroclites sans qu'il n'y ait de réel framework en dessous : donc par exemple, mon projet utilise des sondes 1-Wire DS18B20 (température) et DS28EA00 (température + GPIOs) pourtant proches, je me suis retrouvé avec pleins de code redondant et des API différentes. Pour les frameworks pures C++, comme c'est en dessous du Gcc et comme les ESP ont relativement pas mal de mémoire, il devrait être utilisable ... sauf que les exceptions ne sont pas actives par défaut.

    Hum, je ne suis pas sur d'avoir répondu a ta question ?
    Dernière modification par destroyedlolo ; 21/12/2017 à 09h58.

  21. #18
    Jack

    Re : [Trouvé] c++ : appeler une fonction d'une classe dérivée

    Citation Envoyé par destroyedlolo Voir le message
    Hum, je ne suis pas sur d'avoir répondu a ta question ?
    Pas tout à fait, mais merci en tout cas pour ta réponse.

    Pour être plus précis, je suppose que tu développes sur PC (linux?). Il faut donc une chaîne de compilation croisée pour développer pour le processeur cd l'ESP8266.

  22. #19
    destroyedlolo

    Re : [Trouvé] c++ : appeler une fonction d'une classe dérivée

    Oui, mes machines sont toutes sous Gentoo/Linux.
    La chaine de dev est fournis avec l'IDE, tout est clef en main.

    Cependant, si j'avais utilisé les MakeFile, Gentoo fournit les outils pour créer les cross compilo : tous mes PC participent déjà aux compilation des mes BananaPI (ARM donc) qui sont aussi sous Gentoo. J'utilise Distcc pour faire de la compilation distribuées.
    Pour les ESP, il suffirait de créer la tool chaine avec xtensa-lx106-elf comme cible.

  23. #20
    Jack

    Re : [Trouvé] c++ : appeler une fonction d'une classe dérivée

    Ok, merci.

Discussions similaires

  1. [Programmation] PIC16F : Comment appeler une fonction uniquement au reset externe?
    Par AmigaOS dans le forum Électronique
    Réponses: 15
    Dernier message: 03/08/2017, 11h22
  2. Appeler un tableau dans une fonction
    Par Galibble dans le forum Programmation et langages, Algorithmique
    Réponses: 17
    Dernier message: 28/02/2015, 14h53
  3. Pic C Appeler une fonction dans une interruption
    Par ashen59 dans le forum Électronique
    Réponses: 8
    Dernier message: 02/12/2012, 11h01
  4. Fonction de classe C infini à dérivée positive
    Par Leonhardo dans le forum Mathématiques du supérieur
    Réponses: 10
    Dernier message: 01/03/2010, 23h50
  5. comment appeler une fonction ecrite en C++ sur Matlab
    Par joel dans le forum Logiciel - Software - Open Source
    Réponses: 3
    Dernier message: 17/06/2005, 14h35