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 :

Ecrire à une adresse spécifique


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Bidouilleur amateur
    Inscrit en
    Juin 2006
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur amateur

    Informations forums :
    Inscription : Juin 2006
    Messages : 23
    Par défaut Ecrire à une adresse spécifique
    Bonjour,

    Je croyais que ce problème était banal mais d'après mes recherches sur google comme sur le forum, il semblerait que ce ne soit pas aussi simple que ça.

    Je veux juste écrire à une adresse précise en mémoire. J'essaie donc tout simplement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int *adr;
    adr=0xbfbc7e20;
    *adr=1234;
    printf("L adresse ", adresse , "contient la valeur %x\n", *adresse);
    return 0;
    Quand je lance tout paraît correct sauf que, si je suis le déroulement sous debugger, il n'y a pas du tout la valeur attendue à l'adresse 0xbfbc7e20.

    Donc ma question est : Est-il possible de choisir soit même l'adresse du pointeur ou pas ?

    réf. : http://www.developpez.net/forums/d10...s/#post5859424 post dans lequel souviron34 dit :
    NON !!

    Tu ne PEUX PAS définir toi-même le pointeur d'une variable..
    et pseudocode répond :

    Techniquement, on peut le faire en C.
    Impatient de vos réponses

    Plug

  2. #2
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    618
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 618
    Par défaut
    Je pense que tu peux, à condition que la mémoire t'appartienne (qu'elle ait été alloués par tes soins). Sinon, l'OS te jette.

  3. #3
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Techniquement, c'est possible. Mais le problème, c'est qu'on vit dans un monde magique, celui où l'OS et le processeur fonctionnent ensemble pour segmenter et virtualiser la mémoire. L'OS t'alloue ce qu'on appelle de la mémoire virtuelle, qui n'est pas liée nécessairement à de la mémoire physique. Il garde une table, quelque part, pour faire la translation entre l'adresse que tu pointes et l'adresse physique de la zone mémoire réelle. Du coup, si tu initialises un pointeur avec une valeur de ton cru, il y a à peu près 0 chance pour que ton adresse ainsi spécifiée corresponde à une zone à laquelle l'OS te permettra d'écrire (voire lire). Un accès en écriture ou en lecture à cette adresse va provoquer une erreur de segmentation (violation d'accès sous Windows).

    Maintenant, si tu est dans le monde de l'embarqué, et que tu réalises un OS ou un programme qui tourne sans OS sous-jacent, alors tu aura initialisé l'unité de gestion de mémoire (MMU) du processeur de manière à accéder à toute la mémoire. Du coup, tu peux spécifier une adresse quelconque et lire/écrire à cette adresse. C'est de toute manière ce que fait l'OS pour accéder aux ressources du système (modulo le fait qu'il ne se réserve que des petites parties de l'ensemble de la mémoire : la zone PCI, le bios, etc).

    Dans le monde ancien du DOS (y compris dans le monde des DOS extenders), l'accès à la mémoire n'était pas protégé (dans les DOS extenders, une des première tâche était de donner l'accès à toute la mémoire de la machine, puis de déprotéger cet accès). Il existe aussi des processeurs sans MMU (de plus en plus rares), qui donnent donc de fait un accès non protégé à toute la mémoire adressable. Mais ces vieilleries sont plus ou moins vouées à disparaître (DOS est mort, les processeurs sans MMU sont de moins en moins utilisés : ils l'étaient pour des questions de coût, mais vu le prix d'un processeur ARM de type CortexA9 ou d'un Atom, ça ne vaut vraiment plus le coup de s'ennuyer avec une gestion archaîque de la mémoire).

    Voilà, j'espère avoir fait le tour.

    Pour les liens intéressant :

    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  4. #4
    Membre averti
    Homme Profil pro
    Bidouilleur amateur
    Inscrit en
    Juin 2006
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur amateur

    Informations forums :
    Inscription : Juin 2006
    Messages : 23
    Par défaut "Techniquement c'est possible"
    Tout d'abord, merci de vos réponses

    @pyros : non l'adresse n'appartient pas au prog mais pourtant l'OS ne me jette pas
    Quand je lance tout paraît correct
    @emmanuel : Je choisis une zone mémoire régulièrement allouée par les programmes, ça ne pose donc plus trop de soucis (après quelques segfault ). Que l'allocation se fasse en physique ou en virtuel peu m'importe. J'aimerai juste retrouver sous debugger à l'adresse choisie ce que j'y ai mis dedans (histoire de comprendre un peu ce qui se passe ).
    Petite précision : je suis sous Debian.

    D'autre part tu dis :
    Techniquement, c'est possible.
    Peux-tu développer STP ? Notamment, vois-tu une erreur dans mon code ?

    Encore merci pour ta longue contribution

    Plug

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Par défaut
    Citation Envoyé par ThePlug Voir le message
    Peux-tu développer STP ? Notamment, vois-tu une erreur dans mon code ?
    Factuellement il y a bien une erreur évidente: le print se réfère à une variable nommée adresse alors que juste au-dessus le pointeur s'appelle adr.

    Par ailleurs tu réponds à pyros "l'adresse n'appartient pas au prog mais pourtant l'OS ne me jette pas", et le contraire à emmanuel "Je choisis une zone mémoire régulièrement allouée par les programmes". En effet une zone allouée à un programme appartient dès lors à ce programme.

  6. #6
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    618
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 618
    Par défaut
    Juste une petite précision, une adresse qui t'appartient n'est pas forcement une adresse que tu a alloué à la main avec malloc ou new. Cela peut être une adresse qui pointe quelque part dans ta pile. Par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    int a = 42;
    char b = 10;
    char* c = &b - 3;
    Note: Je ne sais plus s'il faut faire &b - 3 (pour une pile montante) ou &b + 3 (pour une pile descendante), mais l'idée est la même.

    Ici, on pourrait croire que la mémoire pointée par c ne t'appartient pas, mais en fait c pointe quelque part dans la zone mémoire de a. Donc cette mémoire t'appartient bien. Avec un peu de chance ton adresse 0xbfbc7e20 pointe dans ta pile, donc l'OS ne te jette pas. De plus, lorsque tu alloue 1 octet, le systeme t'en alloue en fait beaucoup plus. Je ne détaillerai pas plus pour ne pas dire de bétises, mais juste pour dire qu'il y a beaucoup de mémoire "à toi" dont tu ne soupsonne pas l'existance.

    Bien sûr, ceci ne s'applique que si tu es sous un OS un minimum evolué. Comme l'a dit Emmanuel Deloget, en embarqué ou sur certains "petits" OS, tu as accès à toute la mémoire. Je pense que c'est ce qu'il voulait dire par "Techniquement, c'est possible.".

  7. #7
    Membre averti
    Homme Profil pro
    Bidouilleur amateur
    Inscrit en
    Juin 2006
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur amateur

    Informations forums :
    Inscription : Juin 2006
    Messages : 23
    Par défaut
    Citation Envoyé par estofilo Voir le message
    Factuellement il y a bien une erreur évidente: le print se réfère à une variable nommée adresse alors que juste au-dessus le pointeur s'appelle adr.
    En effet, ce n'est pas la syntaxe valide mais mon problème c'était bien le bout de code avant (@Klaim> je te mets la syntaxe correcte du printf) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
      int *adr;
      adr=(int *)0xbffff600;
      *adr = 0;
      printf("L adresse %p contient la valeur %x\n", adr, *adr);
    return 0;
    Mon problème est de savoir si premièrement :
    remplace bien l'adresse affectée aléatoirement au pointeur par celle imposée (Le mieux sera certainement de vérifier sous débogueur)
    NB : Ne pas oublier le cast (comme j'avais fait au début )
    et deuxièmement si :
    écrit bien dans à l'adresse mémoire choisie.
    J'ai pu vérifier ce dernier point

    Citation Envoyé par Emmanuel Deloget Voir le message
    Mis à part le addresse au lieu de adr, non, il n'y a pas d'erreur - c'est juste un code qui va marcher au petit bonheur la chance
    C'était le sens de ma question quand je disais "peux-tu développer STP" (c'était un jeu de mots ). Donc si mon code est bon, tu as répondu à mon inquiétude. Merci.
    Citation Envoyé par screetch Voir le message
    je n'ai pas compris pourquoi tu voulais ecrire précisément la bas? Il y a quoi dans cette adresse? Ca me parait complètement arbitraire comme valeur, et tu dis toi même que ca marche pas
    Initialement c'était l'adresse d'une variable d'environnement me permettant de communiquer entre 2 programmes. Mais avant de faire des tests sur ça je voudrais valider qu'il est bien techniquement possible d'écrire à une adresse donnée. J'ai donc pris dans mes derniers tests une adresse dans la pile sur remarque pertinente de pyros (merci à lui)

    Prochaine étape = essayer d'identifier les zones dans lesquelles on peut écrire de celles qui segfault

    Plug

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Saut,

    sur un système type windows ou linux, il faut être clair: tu ne peux pas choisir une adresse arbitraire, simplement parce que tu n'as purement et simplement aucune idée des processus qui tournent en plus du tien.

    Pour ce qui est de la distinction entre les adresses qui provoqueront une erreur de segmentation de celles qui ne le feront pas, les seules qui, AMHA ne risqueront pas de le faire seront... les espaces mémoire rajoutés pour raison d'alignement.

    Il faut en effet savoir que les "plus petits types primitifs" (char et short, essentiellement) entrent un certain nombre de fois dans l'espace mémoire qui sépare deux adresses accessibles par le système (on peut ainsi estimer qu'un byte (char) entre quatre fois dans l'espace mémoire qui sépare deux adresses accessibles par un système 32 bits)

    De cette manière, si tu crées une structure contenant, par exemple, un char (c), un short (s) et un int (i) (dans cet ordre), on peut estimer que tu auras la place pour ajouter l'équivalent de trois char à partir de l'adresse de &c+1 et l'équivalent d'un short à partir de l'adresse &s+1 (ou, si tu travailles avec un pointeur sur char, l'équivalent de deux char à partir de &s+2) sans risquer outre mesure d'avoir une errer de segmentation.

    Le problème, c'est toujours (du moins sur les système utilisant un système d'exploitation) que tu n'a aucun moyen de t'assurer qu'une instance donnée de ta structure prendra effectivement place à une adresse particulière!

    L'écriture d'une adresse en dur n'est donc pas du tout une solution envisageable.

    Par contre, tu peux envisager quelque chose comme
    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
    struct MyStruct
    {
        char c;
        short s;
        int i;
    };
    int main()
    {
        MyStruct ms;
        /* récuépration de l'adresse à laquelle se trouve c */
        char* ptr1 = &ms.c;
        /* prendre l'adresse correspondante suivante */
        ++ ptr1;
         for(int i=0;i<3;++i)
         {
            *ptr1 = (0x55 +i);
             ++ptr1;
         }
         return 0;
    }
    et cela ne devrait pas se solder par une erreur de segmentation

    Par contre nous sommes fort loin d'une adresse choisie arbitrairement ;-)
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par ThePlug Voir le message
    Tout d'abord, merci de vos réponses
    @emmanuel : Je choisis une zone mémoire régulièrement allouée par les programmes, ça ne pose donc plus trop de soucis (après quelques segfault ). Que l'allocation se fasse en physique ou en virtuel peu m'importe. J'aimerai juste retrouver sous debugger à l'adresse choisie ce que j'y ai mis dedans (histoire de comprendre un peu ce qui se passe ).
    Petite précision : je suis sous Debian.
    Tu vis dans un monde dangereux. L'adresse que tu as choisi est pour moi une adresse prise au hasard. Si demain l'implémentation de malloc change, hop, ça plante (ne croyez pas que ça n'arrive jamais : la dernière modification majeure date de seulement quelques années ; au lieu de réserver la mémoire de manière systématique par un brk(), malloc() alloue maintenant les grosses zones mémoire en mappant une zone de mémoire partagée).

    Citation Envoyé par ThePlug Voir le message
    Peux-tu développer STP ?
    Mince ! Que rajouter de plus ? Si tu pouvais orienter un peu plus ta question, j'y répondrais au mieux de mes possibilités. Là, c'est trop vague.

    Citation Envoyé par ThePlug Voir le message
    Notamment, vois-tu une erreur dans mon code ?
    Mis à part le addresse au lieu de adr, non, il n'y a pas d'erreur - c'est juste un code qui va marcher au petit bonheur la chance
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  10. #10
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    Je n'utilise que rarement printf alors, c'est un poil hors sujet mais:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("L adresse ", adresse , "contient la valeur %x\n", *adresse);

    On a le droit de faire ça?
    Ou bien c'est du pseudo code?

  11. #11
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par Klaim Voir le message
    Je n'utilise que rarement printf alors, c'est un poil hors sujet mais:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("L adresse ", adresse , "contient la valeur %x\n", *adresse);

    On a le droit de faire ça?
    Ou bien c'est du pseudo code?
    Non. Bien évidemment. Ca affiche tout simplement "adresse" dans la console - les arguments suivants sont ignorés. gcc affiche un warning gros comme une maison de sénateur lorsqu'il trouve du code comme ça.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    printf("adresse %p contient la valeur %x\n", adresse, *addresse);
    Est la ligne de code correcte. Encore mieux, utiliser std::cout, voire une version de printf() orientée C++11 et codée avec des variadic templates (étrange que ça ne fasse pas partie du standard, comme helper).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  12. #12
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    Citation Envoyé par Emmanuel Deloget Voir le message
    mais vu le prix d'un processeur ARM de type CortexA9 ou d'un Atom, ça ne vaut vraiment plus le coup de s'ennuyer avec une gestion archaîque de la mémoire
    C'est un peu HS mais 95% des projets embarqués autour de moi sont au mieux des cortex-R voire des cortex-M. Et là, oublies les MMU... M'enfin, Cortex A et Atom s'approchent plus du PC 'light' que de l'embarqué. Pourquoi choisir encore des cortex R ou M ? Ben parce qu'un industriel, vu les volumes, va voir jusqu'à le quatrième ou le cinquième chiffre après la virgule pour comparer les µ. Parce qu'outre le prix, il y a des conso électrique vraiment différentes. Que des µ + riches impliquent aussi des boards + complexes. Qu'un contrôleur bien enfoui dans ta voiture n'a peut être pas besoin de GPU...
    Ceci dit cela n'enlève rien à la problématique de la discussion : les @ sont rarement en dur dans le code et on utilise autant ce peut le linker pour mapper les objets au bon endroit (y compris pour les MMIO).

  13. #13
    screetch
    Invité(e)
    Par défaut
    je n'ai pas compris pourquoi tu voulais ecrire précisément la bas? Il y a quoi dans cette adresse? Ca me parait complètement arbitraire comme valeur, et tu dis toi même que ca marche pas

Discussions similaires

  1. Ecrire Sur Une ligne Spécifique
    Par Nicolas94 dans le forum Langage
    Réponses: 2
    Dernier message: 09/04/2009, 00h27
  2. Ecrire à une adresse précise
    Par cout dans le forum C
    Réponses: 34
    Dernier message: 19/06/2006, 09h30
  3. ecrire une donnée à une adresse précise
    Par luckydigit dans le forum C
    Réponses: 4
    Dernier message: 16/06/2006, 23h13
  4. Réponses: 8
    Dernier message: 13/10/2005, 10h38
  5. Ecrire l'adresse d'une structure dans un uint32
    Par Steph12 dans le forum C++
    Réponses: 6
    Dernier message: 17/03/2005, 16h31

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