[MFC] Violation d'accès en lecture ? pourquoi ?

Violation d'accès en lecture ? pourquoi ? [MFC] - C++ - Programmation

Marsh Posté le 28-03-2005 à 16:47:52    

:hello:
J'ai un petit soucis avec mes Sockets  :ange:  
 
J'ai un projet sous visual C++: un tableau blanc qui fonctionne en réseau (on dessine chacun de son côté et ca apparait de part et d'autre).
 
J'ai donc un projet avec une classe TableauBlancDoc et une classe TableauBlancView qui hérite de CScrollView.
J'ai une classe TableauBlancSocket qui hérite de CSocket et dans laquelle j'ai un membre de type
TableauBlancView* .
Le but de la classe TableauBlancSocket est de redéfinir OnClose() et OnReceive().
 

Code :
  1. // TableauBlancSocket.cpp : fichier d'implémentation
  2. //
  3. #include "stdafx.h"
  4. #include "Tableau Blanc.h"
  5. #include "TableauBlancSocket.h"
  6. #include ".\tableaublancsocket.h"
  7. #include "Tableau BlancView.h"
  8. // CTableauBlancSocket
  9. CTableauBlancSocket::CTableauBlancSocket()
  10. {
  11. m_View=NULL;
  12. }
  13. CTableauBlancSocket::~CTableauBlancSocket()
  14. {
  15. }
  16. // Fonctions membres CTableauBlancSocket
  17. CTableauBlancSocket::CTableauBlancSocket(CTableauBlancView* v)
  18. {
  19. m_View=v;
  20. }
  21. void CTableauBlancSocket::OnReceive(int nErrorCode)
  22. {
  23. // TODO : ajoutez ici votre code spécialisé et/ou l'appel de la classe de base
  24. if (m_View=NULL) return;
  25. m_View->ProcessPendingRead();
  26. CSocket::OnReceive(nErrorCode);
  27. }
  28. void CTableauBlancSocket::OnClose(int nErrorCode)
  29. {
  30. // TODO : ajoutez ici votre code spécialisé et/ou l'appel de la classe de base
  31. if (m_View==NULL) return;
  32. m_View->ProcessPendingClose();
  33. CSocket::OnClose(nErrorCode);
  34. }


 
 
J'ai une fonction de connection dans mon TableauBlancView.cpp ainsi:
 

Code :
  1. void CTableauBlancView::Connecte()
  2. {
  3. GetDlgItem(ID_CONNEXION_CONNEXION)->EnableWindow(false);
  4. BConnecte=true;
  5. if(GetDocument()->ModeAppli)
  6. {
  7.  //mode serveur
  8.  Serv = new CTableauBlancSocket(this);
  9.  AfxMessageBox("test server 1" );
  10.  Serv->Create(GetDocument()->Port);
  11.  AfxMessageBox("test server 2" );
  12.  Serv->Listen();
  13.  Sock = new CTableauBlancSocket(this);
  14.  Serv->Accept(*Sock);
  15.  AfxMessageBox("Connexion acceptée" );
  16. }
  17. else
  18. {
  19.  // mode client
  20.  Sock = new CTableauBlancSocket(this);
  21.  AfxMessageBox("test client 1" );
  22.  Sock->Create();
  23.  AfxMessageBox("test client 2" );
  24.  Sock->Connect(GetDocument()->AdresseIp,GetDocument()->Port);
  25.  AfxMessageBox("Connexion Etablie" );
  26.  //Sock.Connect(Serveur,Port);
  27.  BConnecte=true;
  28.  //CSocketFile file(&Sock);
  29.  //CArchive arOut(&file,CArchive::store);
  30. }
  31. }


 
 
J'ai cette erreur quand il passe à la ligne: Sock = new CTableauBlancSocket(this);
Exception non gérée à 0x7c239eea (mfc71d.dll) dans Tableau Blanc.exe:0xC0000005: Violation d'accès lors de la lecture de l'emplacement 0x00000020.
 
Le déboggueur pointe cette ligne ASSERT(::IsWindow(m_hWnd) || (m_pCtrlSite != NULL)); de winocc.cpp. Je comprend pas bien pourquoi ca bloque ici.  
Ma classe View héritant de CScrollView lui convient pas ?
 
 
Merci d'avance de votre aide :jap:
Si c'est pas clair, je suis évidemment là  :bounce:


Message édité par Pwill le 31-03-2005 à 19:30:28
Reply

Marsh Posté le 28-03-2005 à 16:47:52   

Reply

Marsh Posté le 28-03-2005 à 17:39:30    

dans la classe principale de ton appli, t'as lancé un AfxSocketInit() ?


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 28-03-2005 à 17:53:53    

Non pas du tout, je vais regarder de plus près cette fonction :jap:

Reply

Marsh Posté le 28-03-2005 à 18:06:56    

J'ai placé AfxSocketInit() dans le constructeur de la classe TableauBlancView. Ca ne change rien, l'appel de  

Code :
  1. Sock = new CTableauBlancSocket(this);

 
ne passe pas, avec la même erreur.
 
Hmm si j'avais oublié d'activer les Windows Socket à la création du projet... il se passerait quoi ?  
 
Sinon, j'ai repris le code de ma prof, mais elle partait d'une classe héritant d'un CDialog. Elle n'avait pas besoin de dessiner quoi que ce soit.
Donc sa classe socket elle a un membre de type CDialog (enfin de la classe qui en hérite).
 
L'erreur porte sur cette fonction de winocc.cpp

Code :
  1. BOOL CWnd::EnableWindow(BOOL bEnable)
  2. {
  3. ASSERT(::IsWindow(m_hWnd) || (m_pCtrlSite != NULL)); // ca passe pas
  4. if (m_pCtrlSite == NULL)
  5.  return ::EnableWindow(m_hWnd, bEnable);
  6. else
  7.  return m_pCtrlSite->EnableWindow(bEnable);
  8. }


 

Reply

Marsh Posté le 28-03-2005 à 18:16:36    

Je rectifie ce que j'ai dit, j'ai bien un AfxSocketInit(), par défaut il est ainsi:
 

Code :
  1. BOOL CTableauBlancApp::InitInstance()
  2. {
  3. // InitCommonControls() est requis sur Windows XP si le manifeste de l'application
  4. // spécifie l'utilisation de ComCtl32.dll version 6 ou ultérieure pour activer
  5. // les styles visuels.  Dans le cas contraire, la création de fenêtres échouera.
  6. InitCommonControls();
  7. CWinApp::InitInstance();
  8. if (!AfxSocketInit())
  9. {
  10.  AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
  11.  return FALSE;
  12. }
  13.         ...
  14. }


 
 

Reply

Marsh Posté le 29-03-2005 à 13:36:51    

La violation d'accès n'est-elle pas liée au paramètre passé au constructeur ?
 
Sock = new CTableauBlancSocket(this);
 
this est un pointeur TableauBlancView  
C'est la classe de base quand on crée un projet application MFC. (avec biduleDoc)

Reply

Marsh Posté le 29-03-2005 à 15:52:23    

Je ne sais pas précisément pourquoi mais je ne peux pas utiliser une instance de la classe de type MonProjetView (MonProjet = nom du projet, ici TableauBlanc, autrement dit c'est la classe qui gère l'affichage et l'intéracion avec l'utilisateur) dans ma classe TableauBlancSocket. Par contre avec une instance de MonProjetDoc, aucun problème à l'initialisation du socket :??:
 
Si quelqu'un voit ce que je veux dire, et pourrait m'expliquer pourquoi, je dis pas non. :jap:

Reply

Marsh Posté le 31-03-2005 à 17:49:12    

Nouveau problème:  
Violation d'accès en lecture à la ligne 10...

Code :
  1. void CTableauBlancDoc::ProcessPendingRead(void)
  2. {
  3. // if (!BConnecte) return;
  4. TRY
  5. {
  6.  AfxMessageBox("dans le try" );
  7.  CDessin* d;
  8.  d= new CCarre;
  9.  AfxMessageBox("Apres carre" );
  10.  if (! Pt_arIn->IsBufferEmpty()) // ici violation d'accès en lecture
  11.   d->Serialize(*Pt_arIn);
  12.  AfxMessageBox("Serialize ok" );
  13.  Elements.Add(d);
  14.  UpdateAllViews(NULL);
  15. }
  16. CATCH (CFileException, e) // ne marche pas avec CArchiveException....
  17. {
  18.  if (Serv!=NULL)
  19.  {
  20.   Serv->Close();
  21.   delete Serv;
  22.   Serv = NULL;
  23.  }
  24.  AfxMessageBox("Connexion perdue" );
  25.  BConnecte = false;
  26. }
  27. END_CATCH
  28. }


 
Déclaré ainsi:

Code :
  1. class CTableauBlancDoc : public CDocument
  2. {
  3. [...]
  4. public :
  5. [...]
  6. CTableauBlancSocket *Serv;
  7. CTableauBlancSocket *Sock;
  8. CSocketFile *Pt_file;
  9. CArchive *Pt_arIn;
  10. CArchive *Pt_arOut;
  11. };


 
Ca fait plus de 2 heures que je revois mon code, fais des tests, sans trop savoir où chercher. Impossible de sérialiser à partir de cette archive.
Pourtant je crois avoir réussi à sérialiser dans Pt_arOut (à partir d'une classe héritant de CScrollView).
 
Pourquoi là je ne peux pas sérialiser dans cette archive à partir de la classe même (CDocument) ou elle est déclarée ??
 
Encore une fois si je ne suis pas clair ou s'il vous manque des bouts de code, je suis là pour un moment  :sarcastic:
Merci de bien vouloir me donner des pistes de recherche  :(


Message édité par Pwill le 31-03-2005 à 18:38:25
Reply

Marsh Posté le 31-03-2005 à 22:02:57    

tu devrais peut-être essayer ça :

Code :
  1. if (Pt_arIn && (! Pt_arIn->IsBufferEmpty()))

Reply

Marsh Posté le 01-04-2005 à 15:14:18    

Je te remercie pour ton attention ;)
 
Ben en fait ca change rien, j'ai toujours la même erreur.
En fait, je viens de remarquer que dans cette fonction il ne faut pas que j'évalue la moindre variable de la classe CTableauBlanc (CDocument) sinon... exception non gérée, violation d'accès en lecture blabla.
 
Pour info, ProcessPendingRead(void) est appelée dans ma classe socket de cette manière:
 

Code :
  1. // TableauBlancSocket.h
  2. #pragma once
  3. class CTableauBlancDoc;
  4. // Cible de la commande CTableauBlancSocket
  5. class CTableauBlancSocket : public CSocket
  6. {
  7. public:
  8. CTableauBlancSocket();
  9. CTableauBlancSocket(CTableauBlancDoc* p);
  10. virtual ~CTableauBlancSocket();
  11. virtual void OnReceive(int nErrorCode);
  12. virtual void OnClose(int nErrorCode);
  13. CTableauBlancDoc* m_Doc;
  14. };
  15. // TableauBlancSocket.cpp
  16. #include "stdafx.h"
  17. #include "Tableau Blanc.h"
  18. #include "TableauBlancSocket.h"
  19. #include ".\tableaublancsocket.h"
  20. #include "Tableau BlancDoc.h"
  21. CTableauBlancSocket::CTableauBlancSocket()
  22. {
  23. m_Doc=NULL;
  24. }
  25. CTableauBlancSocket::CTableauBlancSocket(CTableauBlancDoc* p)
  26. {
  27. m_Doc=p;
  28. }
  29. CTableauBlancSocket::~CTableauBlancSocket()
  30. {
  31. }
  32. // Fonctions membres CTableauBlancSocket
  33. void CTableauBlancSocket::OnReceive(int nErrorCode)
  34. {
  35. // TODO : ajoutez ici votre code spécialisé et/ou l'appel de la classe de base
  36. if (m_Doc=NULL) return;
  37. m_Doc->ProcessPendingRead();
  38. CSocket::OnReceive(nErrorCode);
  39. }
  40. void CTableauBlancSocket::OnClose(int nErrorCode)
  41. {
  42. // TODO : ajoutez ici votre code spécialisé et/ou l'appel de la classe de base
  43. if (m_Doc==NULL) return;
  44. m_Doc->ProcessPendingClose();
  45. CSocket::OnClose(nErrorCode);
  46. }


Message édité par Pwill le 01-04-2005 à 15:16:49
Reply

Marsh Posté le 01-04-2005 à 15:14:18   

Reply

Marsh Posté le 01-04-2005 à 20:14:25    

Pour la suggestion c'est souvent une base d'erreur donc c'était pour ça la petite suggestion ...
et comment est créé et initialisé Pt_arIn ?

Reply

Marsh Posté le 02-04-2005 à 15:08:16    

Code :
  1. void CTableauBlancDoc::Connecte(void)
  2. {
  3. if(ModeAppli)
  4. {
  5.  //mode serveur
  6.  Serv = new CTableauBlancSocket(this);
  7.  if(Serv->Create(Port))
  8.   Serv->Listen();
  9.  else AfxMessageBox(" Socket serv pb create" );
  10.  Sock = new CTableauBlancSocket(this);
  11.  if(Serv->Accept(*Sock))
  12.   AfxMessageBox("Connexion acceptée" );
  13.  else AfxMessageBox("Connexion refusée" );
  14.  Pt_file  = new CSocketFile(Sock);
  15.  Pt_arOut = new CArchive(Pt_file,CArchive::store);
  16.  Pt_arIn  = new CArchive(Pt_file,CArchive::load);
  17. }
  18. else
  19. {
  20.  // mode client
  21.  Sock = new CTableauBlancSocket(this);
  22.  if (Sock->Create()) AfxMessageBox("Create ok" );
  23.  if(Sock->Connect(AdresseIp,Port)) AfxMessageBox("Connect ok" );
  24.  AfxMessageBox("Connexion établie" );
  25.  Pt_file  = new CSocketFile(Sock);
  26.  Pt_arOut = new CArchive(Pt_file,CArchive::store);
  27.  Pt_arIn  = new CArchive(Pt_file,CArchive::load);
  28. }
  29. BConnecte=true;
  30. }


 
Voila la série d'initialisations.
Ca marche assez bien puisque je peux me connecter et me déconnecter à volonté.
Le problème c'est que dans la fonction CTableauBlancDoc::ProcessPendingRead(void) je peux même pas faire de if sur ma variable BConnecte. Si je fais (seulement) un AfxMessageBox("bla" ); dans la foncion ca passe.  
Un simple et unique AfxMessageBox(BConnecte) me sort l'erreur de violation d'acces.
:??:

Reply

Marsh Posté le 02-04-2005 à 15:21:39    

Dans ta fonction :

Code :
  1. void CTableauBlancSocket::OnReceive(int nErrorCode)
  2. {
  3.     // TODO : ajoutez ici votre code spécialisé et/ou l'appel de la classe de base
  4.     if (m_View=NULL) return;
  5.     m_View->ProcessPendingRead();
  6.     CSocket::OnReceive(nErrorCode);
  7. }


 
ton if contient une erreur : m_View == NULL :o

Reply

Marsh Posté le 02-04-2005 à 15:36:24    

:fou: Oh punaise la boulette  :pfff:  :fou:  
Une après midi de perdue et quelques heures  [:morpheusbx]  
La fonction du dessous je ne fais pas l'erreur et suis même pas capable de penser à cette boulette ou faire la comparaison  :cry:  
 
Eh ben voila qui explique tout, ca m'a même pas traversé l'esprit tellement je pensais que je gérais mal mes sockets, sérialisations, etc.
 
:jap: Ben merci !  
Bon binôme qui ne s'est jamais plongé dans le projet n'a rien vu non plus, pourtant ca aurait pu le marquer une telle bétise  :whistle:  
 
Merci à vous deux ! ;)


Message édité par Pwill le 02-04-2005 à 15:39:55
Reply

Marsh Posté le 02-04-2005 à 15:43:39    

Pour éviter ce genre d'erreur par la suite, tu peux mettre
 
if( NULL == m_View )
 
ton compilo te préviendra en cas d'erreur ;)

Reply

Marsh Posté le 02-04-2005 à 15:45:32    

hust a écrit :

Pour éviter ce genre d'erreur par la suite, tu peux mettre
 
if( NULL == m_View )
 
ton compilo te préviendra en cas d'erreur ;)


Vraiment pas lisible en tout cas.


---------------
[:whatde]
Reply

Marsh Posté le 02-04-2005 à 15:47:48    

Question d'habitude je pense :o

Reply

Marsh Posté le 02-04-2005 à 16:04:09    

Oui surement une question d'habitude. Je fais jamais l'erreur de test avec =, suffit que je la fasse dans un projet pour qu'après ca ne me titille même pas l'esprit.
Une violation d'accès ca aurait du me faire tilt que j'avais moi-même mis le truc à null.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed