Violation d'accès lors de la lecture de l'emplacement 0x00000000. [Résolu]

d0jones 10 Messages postés vendredi 29 décembre 2000Date d'inscription 15 janvier 2013 Dernière intervention - 6 nov. 2011 à 12:16 - Dernière réponse : pop70 181 Messages postés mardi 6 avril 2010Date d'inscription 7 janvier 2012 Dernière intervention
- 7 nov. 2011 à 16:52
bonjour,
j'ai un petit souci, quand j'essai d'accéder à la donnée de ma struct j'ai le message suivant :
Exception non gérée à 0x01202029 dans ListTemplate.exe : 0xC0000005: Violation d'accès lors de la lecture de l'emplacement 0x00000000.
Liste.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include 
#ifndef _LIST_
#define _LIST_

using namespace std;
template <typename T>
struct cell 
{	
public:
T data;
cell<T>* next;
};


template <class T>
class Liste
{
public:
Liste(void)
{
this->first=NULL;
this->last=NULL;
this->size=0;
}

Liste(const Liste<T>& list)
{
if (list.size != 0 && list.first != NULL)
{
const  cell<T> *temp = list.first;
while (temp->next != NULL)
{
this->AddInQueue(temp->data);
temp = temp->next;
}
}
}

virtual ~Liste(void)
{
delete(this->first);
delete(this->last);
}

int GetSize()
{
return this->size;
}

void AddInHead(T t)
{
cell<T>* c = new cell<T>();
c->data = t;
c->next = this->first;
this->first = c;
this->size++;
}

void AddInQueue(T t)
{
cell<T>* c = new cell<T>();
c->data = t;
c->next = NULL;
this->last = c;
this->size++;
}

void Concat(const Liste<T>& list)
{
if (list.first != NULL)
{
const  cell<T> *temp = list.first;
while (temp->next != NULL)
{
this->AddInQueue(temp->data);
temp = temp->next;
}
}
}

T ElementAt(int pos)
{
if (pos > this->size)
{
return NULL;
}
else 
{
const cell<T> *temp = this->first;
int cpt = 0;
for (int i=0; i<=pos; i++)
{
if (i == pos)
{
T data = temp->data;
return data;
}
else
{
temp = temp->next;
}
}
/*while (temp->next != NULL)
{
if (cpt == pos)
{
return temp->data;
}
cpt++;
temp = temp->next;
}*/
return -1;
}
}

inline const std::ostream & operator <<(std::ostream & out)
{
if (this->first != NULL)
{
const  cell *temp = this->first;
for (int i = 0; i < this->size; i++)
{
out << (int)temp->data << " - " ; 
temp = temp->next;
} 
}
return out;
}

private:
int size;
cell<T>* first;
cell<T>* last;
};
#endif


le fichier Liste.cpp est vide

le main :

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include 
#include "liste.h"

using namespace std;


int main (int argc, char** argv)
{
Liste* list = new Liste();
cout << "constructeur par defaut : longueur de la liste : " << list->GetSize() <<endl;

list->AddInHead(1);
cout << "ajout en tete de '1' : longueur de la liste : " << list->GetSize() <<endl;
cout << " contenu de la liste : " << list << endl;

list->AddInQueue(2);
cout << "ajout en queue de '2' : longueur de la liste : " << list->GetSize() <<endl;
cout << " contenu de la liste : " << list << endl;

cout << "element a la position 1 : " << list->ElementAt(1) << endl;

Liste* list1 = new Liste();
list1->AddInQueue(3);
list1->AddInQueue(4);
list1->AddInQueue(5);
cout << "creation de la liste 1 contenant les elements '3,4,5'" <<endl;
cout << " contenu de la liste : " << list1 << endl;

list->Concat(*list1);
cout << "concat de list(2) et list1(3) : longeur de la la liste : " << list->GetSize() << endl;
cout << " contenu de la liste : " << list << endl;

Liste* list2 = new Liste(*list);
cout << "constructeur par recopie : longueur de la liste : " << list2->GetSize() << endl;
cout << " contenu de la liste : " << list2 << endl;


char n;
scanf ("%c",&n);
return 0;
}


pourquoi n'y ai je pas accès?
Merci d'avance
Afficher la suite 

Votre réponse

9 réponses

Meilleure réponse
pop70 181 Messages postés mardi 6 avril 2010Date d'inscription 7 janvier 2012 Dernière intervention - 6 nov. 2011 à 14:31
3
Merci
En fait j'en arrive à çeci :
    friend std::ostream& operator <<(std::ostream& out, Liste<T>*& list) //(pour pouvoir faire std::cout << list)
    {
          if (list->ElementAt(0) != NULL)
        {
            const cell<T> *temp = list->GetFirst(); // ici il manque un <T>
            for (int i = 0; i < list->GetSize(); i++)
            {
                out << (T)temp->data << " - " ;
                temp = temp->next;
            }
        }

        return out;
    }


Mais il reste une erreur dans AddInQueue: last pointe sur la dernière cellule, lui affecte sa valeur, et indique que la suivante ne pointera sur rien. Mais à quelle moment la variable next de l'avant-dernière cellule pointe sur la nouvelle
Jamais, donc la liste contient bien le nombre d'éléments voulu, mais ils ne sont pas reliés entre eux... Contrairement à la fonction AddInHead, qui elle fonctionne correctement, et du coup fait planter l'affichage.


C++dialement,

Pop70

Merci pop70 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 101 internautes ce mois-ci

Commenter la réponse de pop70
pop70 181 Messages postés mardi 6 avril 2010Date d'inscription 7 janvier 2012 Dernière intervention - 6 nov. 2011 à 13:36
0
Merci
Salut, à mon avis il y a déjà un problème au niveau de cette ligne :

 const  cell *temp = this->first; 


je mettrais plutôt:

const  cell<T> *temp = this->first; 

sinon je ne pense pas que ça fonctionne.


idem pour

      out << (int)temp->data << " - " ;


comme on ne sait pas quel type doit être affiché :

       out << (T)temp->data << " - " ;


C++dialement,
Pop70
Commenter la réponse de pop70
pop70 181 Messages postés mardi 6 avril 2010Date d'inscription 7 janvier 2012 Dernière intervention - 6 nov. 2011 à 14:06
0
Merci
Et puis surtout :

Il faut indiquer la liste qui est affichée, et pour faire ça il faut rajouter un argument, et aussi que la fonction soit "friend" :

    friend std::ostream& operator <<(std::ostream & out, Liste<T>& list)
    {
        if (list->ElementAt(0) != NULL)
        {
            const cell<T> *temp = list->ElementAt(0);
            for (int i = 0; i < list->GetSize(); i++)
            {
                out << (T)temp->data << " - " ;
                temp = temp->next;
            }
        }
        return out;
    }



Si ça ne fonctionne pas, tu peux essayer une fonction sans opérateur:


   void aff ()
    {
        printf ("\naff:\n---\n");
        cell <T> *temp = first;
        for (int i=0; i < size; i++)
        {

            std::cout << (T)temp->data;
            temp = temp->next;
        }
        printf ("---\n");
    }

et faire list->aff().


Pop70
Commenter la réponse de pop70
d0jones 10 Messages postés vendredi 29 décembre 2000Date d'inscription 15 janvier 2013 Dernière intervention - 6 nov. 2011 à 23:08
0
Merci
Merci pour tes réponses, il n'y a plus de violation d'accès, de plus tu as levé un bug avec AddInQueue.
Encore merci, et bonne fin de week end.
Commenter la réponse de d0jones
d0jones 10 Messages postés vendredi 29 décembre 2000Date d'inscription 15 janvier 2013 Dernière intervention - 6 nov. 2011 à 23:17
0
Merci
De même quand j'ajoute le premier element, il faut que first et last pointe sur celui ci.
Il y a en core deux ou trois petites failles.
Merci
Commenter la réponse de d0jones
cptpingu 3827 Messages postés dimanche 12 décembre 2004Date d'inscription 6 octobre 2018 Dernière intervention - 7 nov. 2011 à 11:16
0
Merci
pop70 a répondu à ta question mais j'aimerais soulever quelques maladresse de code:

#pragma once

Ce n'est pas standard et n'a rien à faire ton code (c'est un pseudo-remplaçant de la guarde que tu as de toute façon écrite).

#include <stdio.h>
#include <stdlib.h>
#include
#ifndef _LIST_
#define _LIST_

Les "includes" devraient être à l'intérieur de la garde et pas au dessus. (Donc les "includes" en dessous du ifndef/define)

using namespace std;

Évite les "using namespace", voir: http://0217021.free.fr/portfolio/axel.berardino/articles/bon-usage-using-namespace

struct cell

En C++, une structure et une classe, c'est la même chose. Donc "cell" devrait avoir une majuscule, et le "public" est inutile, puisqu'une struct est déjà publique par défaut.
De même, généralement un nom de méthode commence par une lettre minuscule.

Liste(void)

Devrait être List(). En C++, une fonction qui ne prend pas d'argument s'écrit comme cela. Il n'y a qu'en C où l'on est obligé de mettre "void".

int size;
cell<T>* first;
cell<T>* last;

On met généralement un différenciateur sur les attributs de classe. Par exemple "first" devrait être "_first".

this->size=0;

Les "this->" sont inutiles, et il est d'usage de ne pas les mettre.


this->first=NULL;
this->last=NULL;

Évite les NULL, voir: [0217021.free.fr/portfolio/axel.berardino/articles/null-en-cpp 0217021.free.fr/portfolio/axel.berardino/articles/null-en-cpp]. Préfère 0 (ou "nullptr" si tu es en C++0x).

Liste(void)
{
this->first=NULL;
this->last=NULL;
this->size=0;
}

Utilise la liste d'initialisation dès que tu le peux ! Devrait être:
Liste()
: _first(0), _last(0), _size(0)
{
}


delete(this->first);

Pas besoin de parenthèse, "delete" est un mot clé et non une fonction. => delete _first;

virtual ~Liste(void)

Le virtual est inutile ici. Tu peux le retirer. => ~Liste()

if (pos > this->size)
{
return NULL;
}
else
{
// code
}

Le "return" est débranchant. Donc il est inutile de mettre un "else". Pas besoin non plus de crochets lorsque tu as une seule instruction.
if (pos > this->size)
return NULL;
                // code

(À corriger partout)

Enfin pour la fonction d'affichage, il est d'usage de ne pas utiliser de friend (ni de cast d'ailleurs). On réalise généralement une fonction publique "print" qui prend un std::ostream en argument. Puis on appelle cette fonction dans la fonction de "sucrement".
Ça permet de laisser la logique au sein de la classe, et de laisser le rôle de sucrement à la fonction de sucrement.

Ex:
Dans ta classe:
    void print(std::ostream& out)
    {
        if (list->ElementAt(0) != 0)
        {
            const cell<T> *temp = list->GetFirst();
            for (int i = 0; i < list->GetSize(); ++i)
            {
                out << temp->data << " - " ;
                temp = temp->next;
            }
        }
    }

En dehors:
    std::ostream& operator <<(std::ostream& out, const Liste<T>& list)
    {
        list.print(out);
        return out;
    }

Ce qui au passage, ne nécessite pas de friend.

Au niveau de ton main:
Pas besoin de faire des new (surtout que tu oublies les delete qui vont avec !).
Tu peux directement remplacer: "Liste* list = new Liste();" par "Liste list;" (et donc toutes les "->" deviennent des ".").
Les includes du C n'ont rien à faire là (donc retire les stdio.h et stdlib.h). Si tu veux mettre une pause, un "std::cin.get()" remplacera avantageusement ton scanf.

Enfin, sépare la déclaration et le code. Il ne devrait pas y avoir de code dans un header.

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
Commenter la réponse de cptpingu
pop70 181 Messages postés mardi 6 avril 2010Date d'inscription 7 janvier 2012 Dernière intervention - 7 nov. 2011 à 12:33
0
Merci
Y'a quelques points sur lesquels je suis pas tout à fait d'accord :

En dehors:

Code C/C++ :

std::ostream& operator <<(std::ostream& out, const Liste<T>& list)
{
list.print(out);
return out;
}

Ce qui au passage, ne nécessite pas de friend.



Sans friend, l'operateur de flux << n'est pas valide, le compilo retournera
...\main.cpp|147|error: 'std::ostream& Liste<T>::operator<<(std::ostream&, Liste<T>*&)' must take exactly one argument


à la différence des opérateurs + - = ...

Sinon pour l'abscence de void je ne suis pas sûr, en C le type de retour par défaut est bien int, mais en C++ ça semble l'être aussi : en l'abscence de type de retour et de retour on obtient un warning :
warning: no return statement in function returning non-void


qui n'est résolu qu'en retournant un entier.

De plus même en retournant un entier, certains compilos (comme Code::Blocks), disent avoir une erreur ISO C++ qui interdit la déclaration sans type :
...\main.cpp|76|error: ISO C++ forbids declaration of 'AddInQueue' with no type|



Sinon pour le reste je suis totalement d'accord

C++dialement,
Pop70
Commenter la réponse de pop70
cptpingu 3827 Messages postés dimanche 12 décembre 2004Date d'inscription 6 octobre 2018 Dernière intervention - 7 nov. 2011 à 13:29
0
Merci
Sans friend, l'operateur de flux << n'est pas valide, le compilo retournera

Attention, ne pas confondre (la version interne):
std::ostream& Liste<T>::operator<<(std::ostream&)
et (la version externe):
std::ostream& operator<<(std::ostream&, const Liste<T>&)
qui sont deux surcharges différentes (qui ont à peu près le même effet, je ne rentre pas dans les détails).

Voici un exemple très simple qui étayera mes dires:
#include 

class Test
{
public:
  Test()
    : _a(1), _b(2), _c(3)
  {
  }

  void print(std::ostream& out) const
  {
    out << _a << " " << _b << " " << _c;
  }
private:
  int _a;
  int _b;
  int _c;
};

std::ostream& operator<<(std::ostream& out, const Test& test)
{
  test.print(out);
  return out;
}

int main()
{
  Test test;

  std::cout << test << std::endl;

  return 0;
}



Sinon pour l'abscence de void je ne suis pas sûr, en C le type de retour par défaut est bien int,

Je parle du void en argument, et non du type de retour. Ex: int func(void) en C++ s'écrit int func().
En C, int func() veut dire "nombre d'argument inconnu" et int func(void) veut dire "pas d'argument".
En C++, la notion de "nombre d'argument inconnu" est retirée, et on a adopté l'écriture "int func()".

Je te remercie des remarques, car tu viens de me faire remarquer que je n'ai peut être pas été clair dans mes explications :)

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
Commenter la réponse de cptpingu
pop70 181 Messages postés mardi 6 avril 2010Date d'inscription 7 janvier 2012 Dernière intervention - 7 nov. 2011 à 16:52
0
Merci
Ah d'accord !
Merci pour les précisions

Sinon j'avais jamais fait la différence entre int funct(void) et int funct() en C ; en fait une fois j'avais essayé les 2 puis fait un objdump, mais le code assembleur était identique (du moins au point de vue du main), donc j'en avais conclu que c'était pareil. Mais du coup j'imagine que int func(void) respecte plus les normes :)



Pop70
Commenter la réponse de pop70

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.