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 :

Vecteur, fonction et erreur de mémoire


Sujet :

C++

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2014
    Messages
    1
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 1
    Points : 1
    Points
    1
    Par défaut Vecteur, fonction et erreur de mémoire
    Bonjour, je suis novice en C++
    J'essaie de créer une fonction prenant pour argument un entier et un vecteur et renvoyant un vecteur multidimensionnel mais visual studio me renvoie une erreur de mémoire que je ne comprends pas. Si quelqu'un pourrait m'aider...
    Voilà la fonction
    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
    vector< vector<double> > Megamatrice(vector<double> donnees, int const k)
     
    {vector<double> kdernieres(k);
       kdernieres=Isoleleskdernieres(donnees,k);  // On isole les k dernières observations
       int const nombrededonnees(donnees.size());
       int const taillemegamatrice (donnees.size()-k);
       int const ligne(3);
       vector< vector<double> > megamatrice(taillemegamatrice, vector<double>(ligne)); //On construit une matrice contenant dans chaque colonne 1. La distance euclidienne 2. L'observation 3. Observation+1 
     
    	   for (int i(0) ; i < taillemegamatrice ; i++)
    	   {megamatrice[i][1]=donnees[i+k-1]; // Pour les deux dernières lignes on a l'observation et l'observation+1 (nécéssaire pour la prévision)
    		megamatrice[i][2]=donnees[i+k];
    		vector<double> kvaleursprecedantsi(k); // Pour chaque i, on crée le vecteur contenant i et les k-1 observations précédants i.
    		for (int j(0) ; j < k ; j++)
    		{kvaleursprecedantsi[j]=donnees[i-k+1+j];
    		}
    		megamatrice[i][0]=Normeeuclidienne(kdernieres,kvaleursprecedantsi); // La première ligne de la matrice contient les distances euclidiennes
    	   }
     
    return megamatrice;
    }
    isoleleskdernieres renvoie les k dernières observations du vecteur. Normeeuclidienne donne la norme euclidienne. Ces fonctions sont OK

    et le main qui teste cette fonction

    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
    int main()
    {int const nombrededonnees(10); 
     int const k(5);
     int const ligne(3);
     vector<double> donnees(nombrededonnees);
     int const taillemegamatrice(donnees.size()-k);
     donnees[0]=3;
     donnees[1]=3.9;
     donnees[2]=4.2;
     donnees[3]=3.3;
     donnees[4]=3.7;
     donnees[5]=7.2;
     donnees[6]=5.3;
     donnees[7]=3.2;
     donnees[8]=4.4;
     donnees[9]=3.1;
     vector< vector<double> > megamatrice(taillemegamatrice, vector<double>(ligne));
     //megamatrice=Megamatrice(donnees, k);
    return 0;
    }
    Merci d'avance

  2. #2
    Membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Serbie

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

    Informations forums :
    Inscription : Octobre 2008
    Messages : 42
    Points : 55
    Points
    55
    Par défaut
    Si tu peux copie ici cet erreur... Si les lignes 4 et 17 sont supprimés (parce que je n'ai pas cette fonctions dans le code), Gcc ne déclare pas des erreurs avec Megamatrice.

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

    Informations professionnelles :
    Activité : aucun

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

    La première chose qui me pique les yeux, c'est de voir que tu essayes de créer... un vecteur de vecteur de double

    Sais-tu qu'il est, la plupart du temps, tout à fait possible de réduire un tableau à deux dimensions, contenant nombre_de_lignes lignes et nombre_de_colonnes colonnes à un tableau à une seule dimension de nombre_de_lignes lignes * nombre_de_colonnes élément

    L'accès à un élément donné se faisant alors en suivant la formule index_element_recherché = ligne_voulue * nombre_colonnes + colonne_voulue.

    Tu as tout à y gagner.

    D'abord, la gestion de ton tableau en est simplifiée : A partir du moment où tu as créé ton vecteur de nombre_de_lignes * nombre_de_colonnes, tu es sur de pouvoir représenter l'ensemble des éléments, sans avoir à t'inquiéter du reste.

    Ensuite, cela te permet, pour autant que tu aies une fonction qui soit dédiée au calcul de l'index, de décider de modifier la manière dont les éléments sont organisés sans risquer de "tout casser" : ils peuvent, selon les besoins, aussi bien être organisés par ligne que par colonne, et le tout, de manière strictement transparente pour l'utilisateur (qui invoquera toujours une fonction proche de size_t toIndex(int ligne_voulue, int colonne_voulue).


    Enfin, cela t'assurera d'avoir des données strictement contiguës en mémoire. Cela pourrait avoir pour conséquence d'éviter de nombreux cahe-miss, ou, si tu préfères, d'éviter que le processeur ne passe presque plus de temps à charger une page de cache qu'à accéder aux données qui s'y trouvent.

    Dans le pire des cas, tu obtiendras des performances similaires à celles que tu obtiendrais avec un tableau à deux dimensions, mais, bien souvent, tu pourras observer un gain appréciable en termes de performances .

    Malgré les apparences, ce n'est pas de l'optimisation prématurée, parce que, ainsi que je l'ai dit, cette approche arrive avec quelques avantages en termes de développement

    Et puis, dans le code même de MegaMatrice, il y a certaines choses qui piquent tout autant les yeux.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vector<double> kdernieres(k);
    Par exemple.

    Bon, d'accord, c'est souvent une bonne idée que de décider de définir la taille d'un vecteur lorsqu'on le déclare. Mais le fait est que tu l'utilises directement après sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    kdernieres=Isoleleskdernieres(donnees,k);
    Or, si j'en crois le code, la fonction Isoleleskdernieres va elle-même créer un tableau de k données qu'elle va s'occuper de remplir.

    Ce n'est pas faux en soi, mais, si on y regarde d'un peu plus près, cette logique va:
    1. forcer l'allocation dynamique d'un espace mémoire suffisant pour permettre de représenter les k élément de kdernieres
    2. forcer (dans Isoleleskdernieres) l'allocation dynamique d'un espace mémoire suffisant pour permettre de représenter les k élément d'une variable temporaire
    3. intervertir (au niveau de l'opérateur = ) les membres (dont l'espace mémoire suffisant pour représenter le k élément) entre le vecteur renvoyé par Isoleleskdernieres (ou peut être une copie de ce vecteur) et kdernieres
    4. (juste au moment de quitter l'opérateur = ) détruire la variable temporaire (qui contient à ce moment là l'espace mémoire alloué à l'origine pour kdernieres) et donc forcer la libération de la mémoire
    Pourquoi ne pas te "contenter" d'un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vector<double> kdernieres=Isoleleskdernieres(donnees,k);
    Tu n'auras que des avantages:
    • le code, ne perd absolument pas en clarté (au contraire, il est d'une certaine manière plus clair)
    • kdernieres est correctement initialisé, mais en plus
    • kdernieres est directement initialisé avec les données qui seront réellement utilisées.
    • Tu pourras au passage profiter de l'élision de copie et, qui sait, peut être même de la sémantique de mouvement (si tu peux profiter des bienfaits de C++11)
    En deux mots : ton code sera plus efficace et plus simple. Elle est pas belle la vie

    Continuons... Je ne vois nulle part où la variable
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int const nombrededonnees(donnees.size());
    est utilisée

    Elle est correctement initialisée, mais -- je suis peut être très fatigué -- je ne vois absolument pas à quoi elle sert. Si elle n'est effectivement pas utilisée, elle n'a strictement rien à faire dans le code .

    On en vient maintenant à la logique proprement dite.

    Comme je te l'ai fait remarquer, il est tout à fait possible de gérer avec un tableau à une dimension l'ensemble des éléments que l'on retrouverait dans un tableau à deux dimensions.

    Nous pourrions donc avoir une logique proche de
    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
    std::vector<double> megamatrice(ligne * taillematrice); // ici, l'ordre n'a pas d'importance :
                                                            // ligne * taillematrice == taillematrice * ligne :D
    for (int i(0) ; i < taillemegamatrice*ligne ; i+=ligne){ // on n'est absolument pas obligé d'incrémenter i...
                                                             // on peut tout à fait le faire varier du nombre d'éléments à "sauter" :D
        megamatrice[i][1]=donnees[i+k-1]; // Pour les deux dernières lignes on a l'observation et l'observation+1 (nécéssaire pour la prévision)
        megamatrice[i+2]=donnee[i+k];
        /* simplifions nous la vie... std::vector vient avec une foule de constructeurs plus
         * sympas les uns que les autres, dont un qui prend deux itérateurs (le premier sur l'élément
         * qui correspond au premier élément du tableau à créé et le deuxième sur "ce qui suit" le
         * dernier élément du tableau à créer).
         * Ce constructeur nous permet tout à la fois de créer le vecteur kvaleursprecedantsi et
         * de l'initialiser directement avec les données qui nous intéresseront :D
         *
         * Dans le cas présent, nous pouvons parfaitement utiliser les adresses des éléments 
         * à prendre en compte comme itérateur.
         */
         std::vector<double> kvaleursprecedantsi(&donnees[i-k],&donnée[i]);//vérifier la logique pour etre sur ;-)
        megamatrice[i]=Normeeuclidienne(kdernieres,kvaleursprecedantsi); // La première ligne de la matrice contient les distances euclidiennes
    }
    Tu peux le remarquer, j'ai ajouté énormément de commentaires qui ne sont là que pour te permettre de comprendre ce que j'ai fait (et qui ne devraient jamais aparaitre dans un code de production ). Si tu enlèves ces commentaires, tu remarqueras que le code est tout à la fois plus lisible et finalement beaucoup plus simple :-D

    Il ne me reste plus qu'une information à te donner en ce qui concerne l'utilisation du vecteur ainsi rempli :
    Tu l'auras compris, les données relatives à chaque éléments sont toutes regroupées, ce qui fait que pour tout i plus petit que megamatrice.size() qui est égale à 0 ou un multiple de 3, tu as:
    • megamatrice[i] correspond à la valeur renoyée par la fonction Normeeuclidienne
    • megamatrice[i+1] correspond à l'observation -1
    • megamatrice[i+2] correspond à l'oservation elle-même.

    autrement dit, tu peux parfaitement envisager une logique qui se rapprocherait de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    for(int i = 0; i< megamatrice.size(), i+=3){
       /* Voici les correspondance observées
        megamatrice[i] --> Normeeuclidienne
        megamatrice[i+1] --> donnees[i+k-1];
        megamatrice[i+2] --> donnees[i+k];
       */
    }
    Elle est pas belle la vie

Discussions similaires

  1. submit form dans fonction JScript, Erreur :(
    Par mbk-w dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 22/05/2006, 13h23
  2. fonction récursive: erreur
    Par calla29 dans le forum Débuter
    Réponses: 3
    Dernier message: 16/05/2006, 12h51
  3. Erreur Allocation mémoire
    Par Thordax dans le forum C++
    Réponses: 10
    Dernier message: 05/04/2006, 22h29
  4. Programme détectant les erreurs de mémoire
    Par gids01 dans le forum MFC
    Réponses: 2
    Dernier message: 07/12/2005, 11h57
  5. [POO] Formulaire HTML + fonction JS = Erreur
    Par bdaboah dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 23/11/2004, 22h59

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