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 :

Multiplication de matrices : "violation d'accès"


Sujet :

C++

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2015
    Messages : 6
    Points : 4
    Points
    4
    Par défaut Multiplication de matrices : "violation d'accès"
    Bonjour,
    Débutant en C++, je fais un programme permettant d'effectuer des opérations de matrices, et je dois surcharger l'opérateur * pour permettre de multiplier deux matrices entre elles.
    la classe de la matrice CMatrice contient 3 données membres :
    nombre de lignes int m_nNlignes, nombre de colonnes int m_nNcolonnes, tableau 2D double** m_pTab.

    Au moment d'exécuter, si m_nNlignes != m_nNcolonnes, le programme plante, en évoquant une violation d'accès...
    Quelqu'un saurait-il d'où viens le problème?
    Je précise que le programme ne rencontre pas de problème avec les autres fonctions (addition de matrices, multiplication par un scalaire, surcharge << et >>, etc.)

    Merci d'avance! Si vous avez besoin d'autres morceaux de code je vous les fournirais bien sûr.

    ma surcharge dans Matrice.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
    22
    23
    24
    25
    26
    CMatrice CMatrice::operator*(const CMatrice& mat)
    {
    	CMatrice resultat;
    	if (m_nNcolonnes == mat.m_nNlignes)
    	{
    		CMatrice resultat(*this);
     
    		resultat.m_nNcolonnes = mat.m_nNcolonnes;
    		resultat.m_nNlignes = m_nNlignes;
    		int m = m_nNlignes;
     
     
    		for (int i = 0; i < resultat.m_nNlignes; i++)
    		{
    			for (int j = 0; j < resultat.m_nNcolonnes; j++)
    			{
    				resultat.m_pTab[i][j] = 0;
    				for (int k = 0; k < m; k++)
    					resultat.m_pTab[i][j] = resultat.m_pTab[i][j] + m_pTab[i][k] * mat.m_pTab[k][j];
    			}
    		}
    	}
    	else cout << "Produit impossible : dimensions incompatibles" << endl;
     
    	return resultat;
    }

  2. #2
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2015
    Messages : 6
    Points : 4
    Points
    4
    Par défaut
    Je précise juste que le programme crash arrivé à la ligne suivante :
    resultat.m_pTab[i][j] = resultat.m_pTab[i][j] + m_pTab[i][k] * mat.m_pTab[k][j]

  3. #3
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Hello,

    Hum, ça sent l'inversion de lignes / colonnes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int m = m_nNlignes;
     
    for (int i = 0; i < resultat.m_nNlignes; i++)
    {
    	for (int j = 0; j < resultat.m_nNcolonnes; j++)
    	{
    		resultat.m_pTab[i][j] = 0;
    		for (int k = 0; k < m; k++)
    			//             [l][c]                  [l][c]         [l][l]             [l][c]
    			resultat.m_pTab[i][j] = resultat.m_pTab[i][j] + m_pTab[i][k] * mat.m_pTab[k][j];
    	}
    }
    A priori, pour m_pTab[i][k], tu utilises 2 indices de ligne. Si nbLignes != nbColonnes alors ya un problème.

  4. #4
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Oui le problème est assez simple:
    1. mettons que this (la matrice à gauche de l'opérateur) fasse 3 lignes et 2 colonnes
    2. tu crées une matrice de résultat qui contient 3 lignes et 2 colonnes par:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CMatrice resultat(*this);
    3. tu changes le décompte des colonnes, mais pas leur nombre (la mémoire qui leur est allouée) par:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    resultat.m_nNcolonnes = mat.m_nNcolonnes;
    4. si tu multiplies avec une matrice de 2 lignes et 3 colonnes, lorsque tu calcules le produit matriciel par:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    resultat.m_pTab[i][j] = resultat.m_pTab[i][j] + m_pTab[i][k] * mat.m_pTab[k][j];
    5. tu écris dans des colonnes qui n'ont pas été allouées et tu obtiens un bon vieux crash

    Moralité:
    - a minima, crée une nouvelle matrice aux dimensions de la matrice de résultat (this->lignes*mat.colonnes)
    - et mieux: l'opérateur de multiplication devrait être en dehors de la classe matrice:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CMatrice operator*(const CMatrice& lhs, const CMatrice& rhs);
    et utiliser des accesseurs sûrs qui préviennent les violations d'accès.

  5. #5
    Membre émérite
    Avatar de Daïmanu
    Homme Profil pro
    Développeur touche à tout
    Inscrit en
    Janvier 2011
    Messages
    696
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur touche à tout

    Informations forums :
    Inscription : Janvier 2011
    Messages : 696
    Points : 2 439
    Points
    2 439
    Par défaut
    Bonsoir.

    Attention à la ligne 2 et 4 il y a deux déclarations de la variable resultat, la seconde du bloc if (m_nNcolonnes == mat.m_nNlignes) masque la première.
    Le resultat renvoyé n'est donc pas le second, mais le premier, celui initialisé par défaut.

    Je suis prêt à parier que double **m_pTab est un pointeur pas ou mal initialisé.
    Peux tu nous montrer le code de ton(tes) constructeur(s) ?

    Ah, et

    Edit: grillé
    Je fais appel aux esprits de Ritchie, Kernighan, Stroustrup et Alexandrescu
    Donnez moi la force, donnez moi le courage de coder proprement !

    « Ça marche pas » n'est PAS une réponse convenable, merci de détailler le souci en fournissant l’environnement, le code source, les commandes et les messages d'erreur.

    Ce club possède également un clavardage, on y trouve quelques perles entre deux sessions d'entraides.

  6. #6
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2015
    Messages : 6
    Points : 4
    Points
    4
    Par défaut
    Bonjour,

    Merci pour vos réponses à mon problème! J'ai suivis vos conseils, cependant j'ai toujours la même erreur.... Je précise que je dois surcharger * (instruction du prof ).

    Je vous donne donc mon programme modifié :

    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
    CMatrice CMatrice::operator*(const CMatrice& mat)
    {
    	CMatrice resultat;
    	if (m_nNcolonnes == mat.m_nNlignes)
    	{
     
    		resultat.set_Nc(mat.m_nNlignes);	//set_Nc : assesseur initialisant m_nNcolonnes;
    		resultat.set_Nl(m_nNlignes);		//set_Nl : assesseur initialisant m_nNlignes;
    		int m = resultat.m_nNlignes;
     
    		//reservation de la memoire
    		//get_Nl() retourne m_nNlignes, get_Nc() retourne m_nNcolonnes
     
    		resultat.m_pTab = new double*[resultat.get_Nl()];	
    		for (int i = 0; i < resultat.get_Nl(); i++)
    		{
    			resultat.m_pTab[i] = new double[resultat.get_Nc()];
    		}
     
     
    		for (int i = 0; i < resultat.get_Nl(); i++)
    		{
    			for (int j = 0; j < resultat.get_Nc(); j++)
    			{
    				resultat.m_pTab[i][j] = 0;
    				for (int k = 0; k < m; k++)
    					resultat.m_pTab[i][j] = resultat.m_pTab[i][j] + m_pTab[i][k] * mat.m_pTab[k][j];
    			}
    		}
    	}
    	else cout << "Produit impossible : dimensions incompatibles" << endl;
     
    	return resultat;
    }
    Voici la déclaration de mes assesseurs en inline dans mon .h :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int get_Nl(){ return m_nNlignes; }
    int get_Nc(){ return m_nNcolonnes; }
    void set_Nl(int L){ m_nNlignes = L; }
    void set_Nc(int C){ m_nNcolonnes = C; }
    Et à votre demande, mon constructeur sans paramètres :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    CMatrice::CMatrice()
    : m_nNlignes(0), m_nNcolonnes(0), m_pTab(NULL)
    {
    }
    EDIT Désolé pour la balise, je ne savais pas comment faire ^^ Maintenant c'est bon!

  7. #7
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    La racine du mal, c'est que tu fais faire trop de choses à ta fonction de multiplication.

    Tu devrais avoir d'autres constructeurs pour ta matrice, en particulier un qui prenne comme argument le nombre de lignes et de colonnes et qui se charge de l'allocation de la mémoire (sur une seule ligne, faisons simple):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CMatrice (unsigned l, unsigned c) : lignes(l), colonnes(c), pmat(new double[l*c]) {}
    Encore mieux, ta classe CMatrice devrait contenir un std::vector qui se charge pour toi de la gestion de la mémoire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CMatrice (unsigned l, unsigned c) : lignes(l), colonnes(c) { vecmat.resize(l*c, 0); } // vecteur de taille l*c initialisé à 0
    Et un accesseur at(unsigned, unsigned):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    double& CMatrice::at(unsigned i, unsigned j) { return vecmat[i*colonnes+j); }
    double CMatrice::at(unsigned i, unsigned j) const { return vecmat[i*colonnes+j); } // n'oublions pas la version const
    Donc:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    CMatrice CMatrice::operator*(const CMatrice& mat) {
    // on se débarrasse d'abord du cas particulier, cela rend le code plus lisible
    if (this->colonnes != mat.lignes) return CMatrice(); // le mieux serait plutôt une exception je pense
    CMatrice resultat(this->lignes, mat.colonnes);
    for (int i = 0; i < resultat.lignes; i++) {
      for (int j = 0; j < resultat.colonnes; j++) {
        for (int k = 0; k < mat.lignes; k++) {
          resultat.at(i,j) += this->at(i,k) * mat.at(k,j);
        }
      }
    }
      return resultat;
    }
    Après bien sûr c'est à polir, lignes et colonnes devraient être des fonctions, etc... Et surtout l'opérateur de multiplication devrait être extérieur à la classe, pas sa méthode.

  8. #8
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2015
    Messages : 6
    Points : 4
    Points
    4
    Par défaut
    Merci pour vos solutions!
    Je vais tenter cela.

Discussions similaires

  1. [XMLDocument] Violation d'accès
    Par xant dans le forum Composants VCL
    Réponses: 8
    Dernier message: 29/09/2004, 15h39
  2. requete / violation d'accès
    Par marie253 dans le forum Bases de données
    Réponses: 4
    Dernier message: 13/08/2004, 13h29
  3. Violation d'acces apres Execute
    Par SegmentationFault dans le forum Connexion aux bases de données
    Réponses: 6
    Dernier message: 10/08/2004, 16h23
  4. [LG]multiplication de matrices
    Par dreamdam dans le forum Langage
    Réponses: 11
    Dernier message: 17/07/2004, 11h02
  5. Violation d'accès apres Close
    Par SegmentationFault dans le forum Bases de données
    Réponses: 3
    Dernier message: 05/07/2004, 16h46

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