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 :

Allouer un espace mémoire toujours à la même variable


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    93
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 93
    Par défaut Allouer un espace mémoire toujours à la même variable
    Bonjour,

    Je programme un JNI en C++ et ma fonction native me génère des bugs mémoire (si j'appelle "trop" ma fonction native) et mon programme me donne de "mauvais" résultats.

    Voici un bout de mon code :
    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
    JNIEXPORT jfloat JNICALL Java_appli_InterfacePI_piar_1value
      (JNIEnv *env, jobject obj, jint numpt, jint date)
    {
        /* On crée une variable de stockage pour la dll */
        HINSTANCE PIAPI32;
        /* On charge la dll */
        PIAPI32 = LoadLibrary("piapi32.dll");
        if (PIAPI32 != NULL)
        {
            char *type = new char;
            long int *iStat = new long int;
            float *rval = new float;
            long int *mode = new long int;
            /* On a besoin du type du point pour connaitre la valeur à retourner */
            typedef long int (*_pipt_pointtype)(long int,char&);
            _pipt_pointtype pipt_pointtype;
            pipt_pointtype = (_pipt_pointtype)GetProcAddress(PIAPI32, "pipt_pointtype");
            pipt_pointtype(numpt,*type);
            typedef long int (*_piar_value)(long int,long int&,long int,float&,long int&);
            _piar_value piar_value;
            #define ARCVALUEBEFORE  1
            *mode=ARCVALUEBEFORE;
            /* On interface la fonction C++ avec la fonction de la dll */
            piar_value = (_piar_value)GetProcAddress(PIAPI32, "piar_value");
            /* On applique la fonction */
            piar_value(numpt,date,*mode,*rval,*iStat);
            /* On libère la dll */
            FreeLibrary(PIAPI32);
            /* On retourne la valeur courante du point suivant son type */
            delete mode;
            if (*type=='R')
            {
                return *rval;
            }
            else if (*type=='D')
            {
                /* On convertit l'entier en float */
                return static_cast<float>(*iStat);
            }
        }
    }
    J'ai deux questions :
    1) Comment puis-je libérer la mémoire de mes variables en gras sachat que j'en ai besoin pour l'instruction return ? (Au passage ai-je bien utilisé l'instruction delete ?)
    2) Sinon comment toujours allouer le même espace mémoire pour ces variables ?

    Merci beaucoup, je suis complètement bloquée :/

  2. #2
    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
    Salut,

    Te rend tu compte que tu ne libère la mémoire que de... mode

    tes variables type, rstat et rval ne prennent pas *énormément* d'espace mémoire, mais, à force d'allouer systématiquement de la mémoire pour eux sans la libérer, tu as une fuite mémoire qui, au final, arrivera à saturer n'importe quel système: ce sont toujours les petits ruisseaux qui font les gros fleuves .

    Il n'y a, d'ailleurs, aucune raison de passer par l'allocation dynamique de la mémoire pour déclarer ces variables, d'autant plus que tu en arrive à... devoir passer en paramètre "ce qui est pointé" par tes pointeurs

    Si tu modifie un tout petit peu ton code pour travailler avec des variables "classiques" au lieu de pointeurs, ton problème se résoudra "tout seul"

    Au final, tu obtiendrait 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
    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
    /* tu es toujours mieux de placer tes define hors fonction */
    #define ARCVALUEBEFORE  1
    /* Ceci dit, il est préférable de créer une constante:
     * const long ARCVALUEBEFORE = 1
     */
    JNIEXPORT jfloat JNICALL Java_appli_InterfacePI_piar_1value
      (JNIEnv *env, jobject obj, jint numpt, jint date)
    {
        /* On crée une variable de stockage pour la dll */
        HINSTANCE PIAPI32;
        /* On charge la dll */
        PIAPI32 = LoadLibrary("piapi32.dll");
        if (PIAPI32 != NULL)
        {
           /* la déclaration d'une variable suffit pour que C++ prévoie
            * l'espace mémoire suffisant pour la stocker
            */
            char type;
            long int iStat; // au fait: long iStat va très bien aussi :D
            float rval;
            long int mode;
            /* On a besoin du type du point pour connaitre la valeur à retourner */
            typedef long int (*_pipt_pointtype)(long int,char&);
            _pipt_pointtype pipt_pointtype;
            pipt_pointtype = (_pipt_pointtype)GetProcAddress(PIAPI32, "pipt_pointtype");
            pipt_pointtype(numpt,*type);
            typedef long int (*_piar_value)(long int,long int&,long int,float&,long int&);
            _piar_value piar_value;
            *mode=ARCVALUEBEFORE;
            /* On interface la fonction C++ avec la fonction de la dll */
            piar_value = (_piar_value)GetProcAddress(PIAPI32, "piar_value");
            /* On applique la fonction */
            piar_value(numpt,date,mode,rval,iStat);
            /* On libère la dll */
            FreeLibrary(PIAPI32);
            if (type=='R')
            {
                return rval;
            }
            else if (type=='D')
            {
                /* On convertit l'entier en float */
                return reinterpret_cast<float&>(iStat);
            }
        }
    }
    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

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    93
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 93
    Par défaut
    Oui oui je m'en rendais compte !!! D'où mon post !
    Du coup, j'ai déclaré mes variables en variables globales et comme ça, le même espace mémoire est réutilisé.
    Mais... car il y a toujours un mais.... ça ne résout pas mon problème pour autant :/

  4. #4
    Membre Expert
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Par défaut
    Bonjour,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Du coup, j'ai déclaré mes variables en variables globales et comme ça, le même espace mémoire est réutilisé.
    Aucune raison de passer par des variables globales dans ton cas.
    La solution que te propose koala01 est bien meilleure et plus "naturelle".

    Il n'y a pas besoin de déclarer de pointeurs ou de faire des allocations :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    /* la déclaration d'une variable suffit pour que C++ prévoie
            * l'espace mémoire suffisant pour la stocker
            */
            char type;
            long int iStat; 
            float rval;
            long int mode;
    Ensuite, les paramètres d'entrée comme *pointeur doivent être remplacés par &valeur. En d'autres termes, l'appel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    pipt_pointtype(numpt,*type);
    ... suite du code ...
    piar_value(numpt,date,*mode,*rval,*iStat);
    devient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    pipt_pointtype(numpt,&type);
    ... suite du code ...
    piar_value(numpt,date,&mode,&rval,&iStat);
    Dans la réponse de koala01, les & n'apparaissent pas (à vérifier donc je me trompe peut-être).

    Remarque 1 : j'ai l'impression que si PIAPI32 est NULL, tu ne renvoies rien dans ta fonction.

    Remarque 2 : peut-être qu'il pourrait être judicieux de déclarer PIAPI32 de façon globale pour ne pas avoir à charger constamment ta dll si tu fais beaucoup d'appels à ta fonction.

    Remarque 3 : koala01 a aussi changer ton static_cast en reinterpret_cast (voir la faq).

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    93
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 93
    Par défaut
    Merci pour toutes ces précisions !

    Concernant :

    Citation Envoyé par Aleph69 Voir le message
    Remarque 2 : peut-être qu'il pourrait être judicieux de déclarer PIAPI32 de façon globale pour ne pas avoir à charger constamment ta dll si tu fais beaucoup d'appels à ta fonction.
    Si je la mets en variable globale ça me génère une erreur ou alors je m'y prends mal (je la place dans l'en tête comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    HINSTANCE PIAPI32;
    ). Comment déclarer une HINSTANCE en variable globale si je ne m'y prends pas correctement ?

  6. #6
    Membre Expert
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Par défaut
    Re,

    il faut utiliser le mot-clé static pour signifier qu'une variable est globale.

    Tu peux aussi faire comme lorsqu'on appelle du C++ depuis Java : charger ta dll à la construction d'une classe.
    Dans ce cas tu peux faire en sorte que ta classe ne soit instanciée qu'une seule et unique fois comme expliqué dans la faq à cet endroit.

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

Discussions similaires

  1. espace mémoire non allouer sur clé USB
    Par khadi8 dans le forum Périphériques
    Réponses: 5
    Dernier message: 13/01/2013, 21h06
  2. [C][obtenir l'espace mémoire libre]
    Par ronan99999 dans le forum Windows
    Réponses: 4
    Dernier message: 26/10/2004, 07h53
  3. Réponses: 4
    Dernier message: 14/06/2004, 09h29
  4. Réponses: 4
    Dernier message: 12/06/2003, 21h42
  5. Accéder à un espace mémoire sous XP
    Par keny dans le forum x86 32-bits / 64-bits
    Réponses: 4
    Dernier message: 02/08/2002, 12h37

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