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

C++ Discussion :

Récupérer un type de variable par une adresse.


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2006
    Messages : 63
    Points : 45
    Points
    45
    Par défaut Récupérer un type de variable par une adresse.
    Bonjours a tous,
    je me demandais si il existait un moyen simple de récupérer un type de variable en passant une adresse ?

    Le but serait de scanner un emplacement mémoire contigu et de récupérer les types de variables le constituant. Je ne sais pas si c'est possibles avec le c++ et la façon dont sont compilés les programmes.

    Avec cette méthode pourrais-je envisager de scanner aussi le contenu de 'this' ? Est-ce que l'objet courant this est stocké de façon contigu dans la mémoire ? Est-ce que c'est propre à la plateforme sur laquelle on tourne, ... ?

    Voila si vous pouviez m'éclairer a ce sujet je vous en saurait gré ^^

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    La mémoire ce n'est qu'une suite de 0 et de 1, ce n'est que le programme qui l'utilise qui lui donne un type et sait comment l'exploiter. Tu veux faire quoi au juste ?

  3. #3
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Salut,

    J'avouerai que je ne comprend pas vraiment ce que tu veux faire...

    Normalement, quand tu utilise une classe, tu sais en gros ce qu'elle contient, et donc le type et le nom de ses membres...

    Si vraiment tu en a besoin, tu peux récupérer certaines informations sur les membre à coup de sizof(), type_id et autre.

    Par contre, il est relativement peu recommandé de faire la moindre hypothèse sur la manière dont les différents membres sont représentés en mémoire:

    Si tu peux être sur que les éléments d'un tableau seront dans des espace mémoire contigu ( char tab[10]), tu ne peux par contre absolument pas être sur de la manière dont sont représentés en mémoire deux membre d'une même classe:

    *Normalement*, tu peux *estimer* qu'ils apparaîtront dans l'ordre de leur déclaration, mais tu ne peux absolument pas préjuger du fait qu'ils utiliseront des espaces mémoire contigus.

    Il est en effet possible que certains membres n'utilisent pas l'espace mémoire qui suit directement celui du membre précédent, parce que le compilateur risque d'effectuer un "alignement des données"

    Le code suivant te permettra de t'en rendre compte
    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
    #include <iostream>
    using namespace std;
    struct MaStruct
    {
        char c;
        int i;
    };
     
    int main()
    {
        cout<<"taille d'un char "<<sizeof(char)<<endl
            <<"taille d'un int "<<sizeof(int)<<endl
            <<"taille normale char + int "<<sizeof(int)+sizeof(char)<<endl
            <<"taille de la structure "<<sizeof(MaStruct)<<endl;
        return 0;
    }
    Chez moi, la sortie console me donne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    taille d'un char 1
    taille d'un int 4
    taille normal char + int 5
    taille de la structure 8
    ce qui montre bien que le compilateur a aligné les données (3 octets de plus) pour que les différents membres se trouvent à des adresses mémoire bien précises

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2006
    Messages : 63
    Points : 45
    Points
    45
    Par défaut
    Ok merci pour ces précisions !

    En fait j'essais de faire une petite hierarchie d'objets dont l'objet principale (la classe de base quoi) permettrai de faire un peu d'introspection. D'ou le fait de vouloir "scanner" le contenu de this.

    Sinon existe-t-il des directives de compilation pour éviter cette "alignement de données"? Est-ce que ça à le meme but que le padding des bitmaps, accélérer les traitements ?

    Est-ce qu'en plus du probleme de l'alignement des données l'os lui meme peut disperser le contenu d'un objet en mémoire (je ne parle pas du heap) ?

  5. #5
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    L'introspection est très difficile à réaliser en C++, ce n'est pas prévu pour. C'est plus un truc de langages interprétés.

    En tout cas ce n'est pas comme ça que ça marche, après compilation il ne reste plus grand chose d'exploitable.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2006
    Messages : 63
    Points : 45
    Points
    45
    Par défaut
    Citation Envoyé par Laurent Gomila Voir le message
    L'introspection est très difficile à réaliser en C++, ce n'est pas prévu pour. C'est plus un truc de langages interprétés.

    En tout cas ce n'est pas comme ça que ça marche, après compilation il ne reste plus grand chose d'exploitable.
    Effectivement j'ai pu constater qu'il n'y avait pas grand chose de préétablie pour, ne serait-ce que du coté de la fonction typeid() name() qui en standard fait fi de tous les standards!

    Cela dit si les données sont éparpillées en mémoire existerait -il un moyen de les rassemblé en un bloc en mémoire ? Par example je crois que mmap prends des données sur disque et les rassemble en un bloc en mémoire, il pourrait exister quelque chose de similaire pour les données mémoire ?

  7. #7
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Points : 444
    Points
    444
    Par défaut
    En fait cet alignement est dû aux limites physiques ton ordi ; si la mémoire est sensée fonctionnée sur des mots de 4 octets, le compilo se débrouillera pour que toute donnée soit le début d'un mot, le reste est gaspillé.

    Il y a des directives de compilation pour éviter cela en partie, bien que ça puisse fortement faire chuter les performances voire carrément planter le programme dans certains cas. Et ça ne te garantira pas qu'une "grosse" structure sera contigüe en mémoire.

    Bref se baser sur la mémoire pour faire de l'introspection n'est pas possible, tu n'aras de toute manière pas le même résultat d'un OS à l'autre, ni d'un type de proc à un autre.

  8. #8
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Ceci dit, on peut remarquer certaines "particularités"...

    Comme le laisse présumer mon message précédent, il y entre quatre "char" dans un "int" (ca dépend de pas mal de choses, mais, bon, c'est le cas chez moi )

    Hé bien, si on déclare 4 membres de type "char" et un membre de type "int", on remarque que la taille dépendra de la position des caractères :
    Si les 4 caractères sont regroupés
    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
    struct MaStruct
    {
        char c1;
        char c2;
        char c3;
        char c4;
        int i;
    };
    /* ou */
    struct MaStruct
    {
        int i;
        char c1;
        char c2;
        char c3;
        char c4;
    };
    /* ou encore, ce qui est finalement logique */
    struct MaStruct
    {
        char tab[4];
        int i;
    }
    la taille de la structure reste de ... 8

    Par contre, si un seul des caractères est séparé des autres
    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
    struct MaStruct
    {
        char c1;
        int i;
        char c2;
        char c3;
        char c4;
    };
    /* ou */
    struct MaStruct
    {
        char c1;
        char c2;
        int i;
        char c3;
        char c4;
    };
    la taille de la structure passera à... 12 (perte de l'espace pour 3 caractères entre c1 et i et d'un caractère apres c4 )

  9. #9
    screetch
    Invité(e)
    Par défaut
    hello,

    l'introspection est un truc tres tres utile en general mais completement indisponible en C++

    j'ai ecris une bibliotheque de RTTI/introspection, ca prend du temps et c'est pas si facile :-/

    mais au final, le jeu peut en valoir la chandelle; dans mon cas, apres avoir ecrit le RTTI, en environ 3 heures de boulot j'ai ensuite branché basiquement le langage LUA sur le RTTI, ce qui me permet d'appeler des methodes C++ depuis Lua en deux coups de cuiller a pot.

    En bref, si tu vas vers un projet long et consequent c'est une tres bonne idee de penser des le debut a de l'introspection. Sinon, oublie carrement, c'est une tache assez lourde alors si c'est pour l'utiliser tous les 36 du mois c'est du temps et des neurones perdus ^^

    il existe des langages plus orientes RTTI comme C# et Java, peut etre devrais tu te tourner vers un de ceux la.

  10. #10
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Lua et le C sont emboitable ensemble très facilement.
    Ensuite pour lua et le C++ ,ya des bindings.
    Pas besoin de se casser la tête avec du RTTI.

  11. #11
    screetch
    Invité(e)
    Par défaut
    alors disons qu'en 3 heures de plus et sans toucher a la partie RTTI j'ai ajouté le binding vers Squirrel (certes assez inspire de Lua)

    et qu'en 3 heures de plus j'ai mappé deux ou trois objets GTK (je n'arrive pas a le faire automatiquement mais presque)

    et que maintenant j'ai une solution generique permettant a Lua ou a Squirrel d'acceder au moteur ou a GTK+

    tout cela avec le RTTI

    certes il est possible d'utiliser des bibliotheques pour le faire mais il faut une bibliotheque par langage. Par exemple j'aurai pu le faire avec le binding Lua vers le C++ ET le binding Squirrel vers le C++ ET le binding GTKLua ET le binding (peut etre inexistant) GtkSquirrel.


    Enfin, lua ne permet pas plus le RTTI, j'avais fait le RTTI a la base pour l'introspection et une consequence est de pouvoir exposer l'API a lua, une autre est de pouvoir inspecter les valeurs en runtime, une troisieme est de pouvoir modifier par le reseau les valeurs, etc etc.

  12. #12
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Ca se comprend beaucoup mieut vu comme ca.

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

Discussions similaires

  1. Réponses: 6
    Dernier message: 18/03/2009, 17h25
  2. Réponses: 6
    Dernier message: 14/01/2008, 16h30
  3. Type incompatible retourné par une méthode
    Par beegees dans le forum Langage
    Réponses: 4
    Dernier message: 22/04/2007, 19h23
  4. [MySQL] Récupération du type de variable d'une colonne
    Par Nephret dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 08/02/2007, 13h43
  5. Réponses: 2
    Dernier message: 16/10/2003, 17h17

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