IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

wxWidgets Discussion :

[wxWidgets] Allocation statique et dynamique


Sujet :

wxWidgets

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 142
    Points : 89
    Points
    89
    Par défaut [wxWidgets] Allocation statique et dynamique
    Bonjour à tous

    J’obtiens un bug assez étrange à la fermeture de mon programme (sans warning ni rien à la compilation). J’ai réduit le code au minimum afin de vous en montrer le minimum, par soucis de simplicité.
    Voilà comment il se décompose :
    - App.h/cpp, point d’entrée du programme.
    - Controller.h/cpp, le contrôleur de mon MVC (mais peu importe), chargé dynamiquement (avec un new, donc) par la méthode d’initialisation de la classe App.
    Dans le constructeur de cette dernière classe, je crée et affiche une fenêtre vide (de type wxFrame), chargée statiquement.

    Une fois la fenêtre fermée et le programme en cours d’arrêt, j’obtiens ce message :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    GLib-GObject-CRITICAL **: g_object_unref: assertion `G_IS_OBJECT (object)' failed
    Voici le code des différents fichiers évoqués (j’ai laissé les directives de compilation par soucis d’exhaustivité, mais c’est très classique, je pense que vous pouvez les ignorer dans un premier temps) :

    App.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #include <wx/wxprec.h>
     
    #ifdef __BORLANDC__
    	#pragma hdrstop
    #endif
     
    #ifndef WX_PRECOMP
    	#include <wx/wx.h>
    #endif
     
    #include "Controller.h"
     
    class App : public wxApp
    {
    	public:
    		bool OnInit();
    		int OnExit();
     
    	private:
    		const Controller* controller;
    };
     
    #endif
    App.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include "wx_pch.h"
     
    #ifdef __BORLANDC__
        #pragma hdrstop
    #endif
     
    #include "App.h"
     
    IMPLEMENT_APP(App);
     
    bool App::OnInit()
    {
    	controller = new Controller();
    	return true;
    }
     
    int App::OnExit()
    {
    	delete controller;
    	return 0;
    }
    Controller.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #ifndef _CONTROLLER_H
    #define _CONTROLLER_H
     
    #include <wx/wxprec.h>
     
    #ifdef __BORLANDC__
    	#pragma hdrstop
    #endif
     
    #ifndef WX_PRECOMP
    	#include <wx/wx.h>
    #endif
     
    class Controller
    {
    	public:
    		Controller();
     
    	private:
    		wxFrame frame;
    };
     
    #endif
    Controller.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include "wx_pch.h"
     
    #ifdef __BORLANDC__
    	#pragma hdrstop
    #endif
     
    #include "Controller.h"
     
    Controller::Controller():
        frame(0L, wxID_ANY, _("test"))
    {
    	frame.Show();
    }
    Le fichier wx_pch.h est une en-tête de précompilation qui ne présente je pense aucun intérêt à être montré.


    Ce que je n’explique pas, c’est que je n’obtiens plus aucune erreur si je charge la fenêtre (wxFrame frame) dynamiquement (avec un new).

    Je me pose donc la question : Est-ce une erreur en C++ d’effectuer des chargements statiques à partir d’un objet qui a été chargé dynamiquement (et que du coup ça foutrait le boxon dans la gestion pile/tas) ?


    Autre interrogation :
    Si j’ajoute à ma classe Controller (la version avec le chargement statique de la frame) un attribut de n’importe quel type, même un int, à l’extinction toujours une erreur, mais plus la même (je laisse le backtrace et le memory map, je sais pas trop bien comment lire ça, mais ça cache peut-être des indices) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    *** glibc detected *** /home/florian/Development/App/bin/Debug/App: free(): invalid pointer: 0x080a04cc ***
    ======= Backtrace: =========
    /lib/i686/cmov/libc.so.6[0xb73abeed]
    /lib/i686/cmov/libc.so.6(cfree+0x90)[0xb73af530]
    /usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0xb7585611]
    /usr/lib/libwx_gtk2ud_core-2.8.so.0(_ZN7wxFrameD0Ev+0x8a)[0xb79bb4cc]
    /usr/lib/libwx_gtk2ud_core-2.8.so.0(_ZN9wxAppBase20DeletePendingObjectsEv+0x9d)[0xb79f2945]
    /usr/lib/libwx_gtk2ud_core-2.8.so.0(_ZN9wxAppBase6OnIdleER11wxIdleEvent+0x2f)[0xb79f29b5]
    /usr/lib/libwx_baseud-2.8.so.0(_ZNK12wxAppConsole11HandleEventEP12wxEvtHandlerMS0_FvR7wxEventES3_+0x41)[0xb7622f2d]
    /usr/lib/libwx_baseud-2.8.so.0(_ZN12wxEvtHandler21ProcessEventIfMatchesERK21wxEventTableEntryBasePS_R7wxEvent+0xe0)[0xb76dfd2c]
    /usr/lib/libwx_baseud-2.8.so.0(_ZN16wxEventHashTable11HandleEventER7wxEventP12wxEvtHandler+0xd8)[0xb76e1b36]
    /usr/lib/libwx_baseud-2.8.so.0(_ZN12wxEvtHandler12ProcessEventER7wxEvent+0x13b)[0xb76e1c99]
    /usr/lib/libwx_gtk2ud_core-2.8.so.0(_ZN9wxAppBase11ProcessIdleEv+0xe8)[0xb79f279a]
    /usr/lib/libwx_gtk2ud_core-2.8.so.0[0xb79234d4]
    /usr/lib/libglib-2.0.so.0[0xb7042bf1]
    /usr/lib/libglib-2.0.so.0(g_main_context_dispatch+0x182)[0xb7044952]
    /usr/lib/libglib-2.0.so.0[0xb704791f]
    /usr/lib/libglib-2.0.so.0(g_main_loop_run+0x1a9)[0xb7047cc9]
    /usr/lib/libgtk-x11-2.0.so.0(gtk_main+0xb4)[0xb6df2574]
    /usr/lib/libwx_gtk2ud_core-2.8.so.0(_ZN11wxEventLoop3RunEv+0xa0)[0xb7943986]
    /usr/lib/libwx_gtk2ud_core-2.8.so.0(_ZN9wxAppBase8MainLoopEv+0x61)[0xb79f22ad]
    /usr/lib/libwx_gtk2ud_core-2.8.so.0(_ZN9wxAppBase5OnRunEv+0x2f)[0xb79f1f67]
    /usr/lib/libwx_baseud-2.8.so.0(_Z7wxEntryRiPPw+0xa6)[0xb766b7ba]
    /usr/lib/libwx_baseud-2.8.so.0(_Z7wxEntryRiPPc+0x37)[0xb766b885]
    /home/florian/Development/Fabulous Novel Creator/bin/Debug/Fabulous Novel Creator[0x804afa2]
    /lib/i686/cmov/libc.so.6(__libc_start_main+0xdc)[0xb7359ebc]
    /home/florian/Development/App/bin/Debug/App(_ZN9wxAppBase9SetActiveEbP8wxWindow+0x49)[0x804a521]
    ======= Memory map: ========
    08048000-0804c000 r-xp 00000000 03:0c 3276912    /mnt/data/Development/App/bin/Debug/App
    0804c000-0804d000 rw-p 00003000 03:0c 3276912    /mnt/data/Development/App/bin/Debug/App
    0804d000-080d6000 rw-p 0804d000 00:00 0          [heap]
    b6400000-b6421000 rw-p b6400000 00:00 0 
    b6421000-b6500000 ---p b6421000 00:00 0 
    b65cc000-b65ea000 r--p 00000000 03:05 217426     /usr/share/locale/fr/LC_MESSAGES/libc.mo
    b65ea000-b65fc000 r-xp 00000000 03:05 315551     /usr/lib/gtk-2.0/2.10.0/engines/libmurrine.so
    b65fc000-b65fd000 rw-p 00012000 03:05 315551     /usr/lib/gtk-2.0/2.10.0/engines/libmurrine.so
    b65fd000-b6627000 r-xp 00000000 03:05 212911     /usr/lib/libgnomecanvas-2.so.0.1400.0
    b6627000-b6628000 rw-p 0002a000 03:05 212911     /usr/lib/libgnomecanvas-2.so.0.1400.0
    b6628000-b6665000 r-xp 00000000 03:05 222972     /usr/lib/libgnomeprintui-2-2.so.0.1.0
    b6665000-b6667000 rw-p 0003d000 03:05 222972     /usr/lib/libgnomeprintui-2-2.so.0.1.0
    b6667000-b667c000 r-xp 00000000 03:05 221309     /usr/lib/libart_lgpl_2.so.2.3.19
    b667c000-b667d000 rw-p 00014000 03:05 221309     /usr/lib/libart_lgpl_2.so.2.3.19
    b667d000-b66e0000 r-xp 00000000 03:05 222912     /usr/lib/libgnomeprint-2-2.so.0.1.0
    b66e0000-b66e2000 rw-p 00063000 03:05 222912     /usr/lib/libgnomeprint-2-2.so.0.1.0
    b66e2000-b6705000 r--p 00000000 03:05 221188     /usr/share/locale/fr/LC_MESSAGES/gtk20-properties.mo
    b6705000-b670e000 r-xp 00000000 03:05 506941     /lib/i686/cmov/libnss_files-2.5.so
    b670e000-b6710000 rw-p 00008000 03:05 506941     /lib/i686/cmov/libnss_files-2.5.so
    b6710000-b6718000 r-xp 00000000 03:05 506936     /lib/i686/cmov/libnss_nis-2.5.so
    b6718000-b671a000 rw-p 00007000 03:05 506936     /lib/i686/cmov/libnss_nis-2.5.so
    b671a000-b672d000 r-xp 00000000 03:05 506922     /lib/i686/cmov/libnsl-2.5.so
    b672d000-b672f000 rw-p 00012000 03:05 506922     /lib/i686/cmov/libnsl-2.5.so
    b672f000-b6731000 rw-p b672f000 00:00 0 
    b6731000-b6738000 r-xp 00000000 03:05 506928     /lib/i686/cmov/libnss_compat-2.5.so
    b6738000-b673a000 rw-p 00006000 03:05 506928     /lib/i686/cmov/libnss_compat-2.5.so
    b6743000-b6749000 r--p 00000000 03:05 224516     /usr/share/locale/fr/LC_MESSAGES/glib20.mo
    b6749000-b675a000 r--p 00000000 03:05 221187     /usr/share/locale/fr/LC_MESSAGES/gtk20.mo
    b675a000-b6882000 r--p 00000000 03:05 245555     /usr/lib/locale/locale-archive
    b6882000-b6885000 rw-p b6882000 00:00 0 
    b6885000-b68af000 r-xp 00000000 03:05 221286     /usr/lib/libpangoft2-1.0.so.0.1600.4
    b68af000-b68b0000 rw-p 00029000 03:05 221286     /usr/lib/libpangoft2-1.0.so.0.1600.4
    b68b0000-b68c5000 r-xp 00000000 03:05 214265     /usr/lib/libICE.so.6.3.0
    b68c5000-b68c6000 rw-p 00014000 03:05 214265     /usr/lib/libICE.so.6.3.0
    b68c6000-b68c8000 rw-p b68c6000 00:00 0 
    b68c8000-b68cc000 r-xp 00000000 03:05 214001     /usr/lib/
    Press ENTER to continue.

    Merci beaucoup d’avoir lu jusqu’ici !

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Je me pose donc la question : Est-ce une erreur en C++ d’effectuer des chargements statiques à partir d’un objet qui a été chargé dynamiquement (et que du coup ça foutrait le boxon dans la gestion pile/tas) ?
    Bien sûr que non.

    Le problème, c'est wxwidgets, qui appelle automatiquement delete sur tes variables. (voir ce lien par exemple, c'est marrant j'ai pas trouvé de bonne explication de la gestion mémoire dans la doc...)

    Si tu veux un truc qui te permette une utilisation normale du C++, tourne toi plutôt vers GTKmm.

  3. #3
    Membre émérite
    Avatar de Ti-R
    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Avril 2003
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 683
    Points : 2 568
    Points
    2 568
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class Controller
    {
    	public:
    		Controller();
     
    	private:
    		wxFrame frame;
    };
    A réécrire en:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class Controller: public wxFrame
    {
    	public:
    		Controller();
     };

    Réécrire cette partie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Controller::Controller():
        frame(0L, wxID_ANY, _("test"))
    {
    	frame.Show();
    }
    en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Controller::Controller()
    {
     
    	wxFrame::Create(parent, id, caption, pos, size, style);
    }
    Enfin, il faut revoir tout ton code, regarde dans le répertoire "sample" fournit avec wxWidgets!

    Citation Envoyé par loufoque
    Le problème, c'est wxwidgets, qui appelle automatiquement delete sur tes variables. (voir ce lien par exemple, c'est marrant j'ai pas trouvé de bonne explication de la gestion mémoire dans la doc...)
    Oui, mais ce n'est pas magique non plus, tout ce que tu créer et donne à wxWidgets sera détruit par défaut, sauf si tu détaches tes composants d'autres composants. C'est pour cela qu'il faut toujours allouer dynamiquement !

    Il faut lire la documentation "three minute hero", surtout que c'est plutôt bien fournit, il y a aussi un wiki bien fourni.

    Le tout est très facile à utiliser dès qu'on a compris le système.

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 142
    Points : 89
    Points
    89
    Par défaut
    Ti-R> J’imagine que ton code fonctionne, vu qu’il revient à charger dynamiquement une fenêtre à partir de App.

    Seulement, je voudrais charger statiquement cette même fenêtre*. Je sais bien que les samples fournis avec wxWidgets le fait dynamiquement, et j’ai peut-être tort de persister, mais charger un objet dans la pile me semble tout de même plus rapide.
    De plus, je ne vois pas l’intérêt (peut-être à tort) de charger dynamiquement un objet qui devra être chargé de toute façon, et qui le restera tout le long de l’exécution du programme (l’allocation dynamique sert bien à charger des objets qu’on est pas sûr d’avoir à l’exécution, des objets de même type dont on ne connais pas le nombre à l’avance, ou des objets lourds qui ne doivent pas être nécessairement tout le temps chargés ?).

    *C’est justement pour ça que je crée une classe Controller à part de App, le point d’entrée du programme.
    En effet, on n’a pas accès au constructeur de la classe wxApp, ce qui nous empêche de faire toute initialisation d’un éventuel champ (wxFrame ou autre) chargé statiquement. Et de toute façon, même une tentative de chargement d’un objet dont la classe comprend un constructeur par défaut fout la merde à l’exécution (ou à la compilation, je sais plus, faudra que je reteste).

    D’ailleurs, comment le chargement statique d’un objet B à partir d’un objet A chargé dynamiquement (donc dans le tas), peut-il produire le chargement de l’objet B dans la pile (alors que la pile impose un chargement et déchargement dans l’ordre) ?

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 142
    Points : 89
    Points
    89
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    D’ailleurs, comment le chargement statique d’un objet B à partir d’un objet A chargé dynamiquement (donc dans le tas), peut-il produire le chargement de l’objet B dans la pile (alors que la pile impose un chargement et déchargement dans l’ordre) ?
    Pour ce coup je vais essayer de me répondre à moi-même…
    Étant donné que B est statiquement lié à A, « A et B » ne font qu’un bloc, donc en chargeant dynamiquement A dans le tas, on en fait implicitement de même pour B. Du coup, ni A ni B ne sont chargés dans le tas.

    Et comme il n’est apparemment pas possible de charger statiquement un objet à partir de l’objet étant le point d’entrée du programme, ça veut dire que tout est balancé dans le tas. Donc ça ne sert à rien de faire des allocations statiques, si ce n’est que les blocs ne sont au moins pas fragmentés partout dans la RAM, à défaut d’être bien rangés dans la pile.

    J’ai bon ?

  6. #6
    Membre émérite
    Avatar de Ti-R
    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Avril 2003
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 683
    Points : 2 568
    Points
    2 568
    Par défaut
    Franchement, je crois que tu cherches compliqués pour pas grand chose, et optimiser quoi ?

    Tu as vu à la vitesse ou la fenêtre se lance ?
    De plus la philosophie de toute la bibliothèque repose sur l'allocation dynamique.

    Et je pense que chercher à optimiser cela n'a aucun intérêt, une fenêtre se lance une fois, ce n’est pas du traitement d'image avec un algorithme qui se lance plusieurs millions de fois. Si c’est passer 3/4 jours pour faire une bidouille pour "gagner" moins de 1 ms, même si c’est 10ms (ce que je doute)… je ne vois pas l’intérêt, personne ne se rendra compte de ton optimisation maison, et si quelqu'un reprend ton code, il va se dire, "Mais qu'es ce qu'il nous à fait " .

  7. #7
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    +1

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 142
    Points : 89
    Points
    89
    Par défaut
    Arf, ouais, je me complique l’existence, en effet. J’suis un gros perfectionniste acharné
    Je vais rester dans le simple, ça vaut mieux.

    En tout cas, un grand merci à vous tous pour vos réponses !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 8
    Dernier message: 26/04/2012, 11h27
  2. Agrégation: statique ou dynamique
    Par icer dans le forum C++
    Réponses: 13
    Dernier message: 04/03/2006, 15h48
  3. [debutant] : Allocation de mémoire dynamique
    Par sam.fet dans le forum Langage
    Réponses: 5
    Dernier message: 15/02/2006, 14h58
  4. char *, string et tableau statique ou dynamique
    Par salseropom dans le forum C
    Réponses: 2
    Dernier message: 05/12/2005, 11h33
  5. Réponses: 2
    Dernier message: 19/08/2005, 16h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo