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

Messages postés
6
Date d'inscription
lundi 16 avril 2007
Statut
Membre
Dernière intervention
16 décembre 2010
- - Dernière réponse : 3Fred9
Messages postés
6
Date d'inscription
lundi 16 avril 2007
Statut
Membre
Dernière intervention
16 décembre 2010
- 29 mars 2010 à 11:49
Bonjour,

J'ai changé de compilateur de Visual C++ 6 à Visual Studio 2005 et depuis j'ai une fonction qui plante à l'exécution par une violation d'accès comme mentionnée dans le titre.

Pour simplifier j'ai une structure définie dans un . h

typedef struct Instance_s {
long Instance;
char *DocName;
char *Header;

Record_s *RecordList;
Record_s *LastRecord;

struct Instance_s *Previous;
struct Instance_s *Next;

char* Collation;
} Instance_s;


Les fonctions sont écrits dans un projet compilés dans une dll.
La première fonction qui est appelée et qui initialise la structure ne pose aucun soucis :


bool ACG_IMPORT WORD97_NewInstance(ObCharFld &RS,
   ObLongFld &Instance,
   ObCharFld &DocName,
   AzCPrint_Collation &Collation)
{

Instance_s *I;
int Len;

//-- Définition de la variable "dn" et affectation avec la chaine "DocName".
char *dn = DocName.GetText();
char *lCollation = Collation.GetText();

//-- Creation d'une entité "I", instance de la classe "Instance_s".
I = new Instance_s;

//-- Remplissage de toute la structure mémoire de "I" avec des zéros.
memset(I, 0, sizeof(I));


//-- Allocation d'une nouvelle zone mémoire à "I->DocName" et recopie
//   de la chaine "dn" (Nom du document) dans cette zone mémoire.

Len = strlen(dn) + 1;
I->DocName = new char[Len];
memcpy(I->DocName, dn, Len);

//Collation
Len = strlen(lCollation) + 1;
I->Collation = new char[Len];
memcpy(I->Collation, lCollation, Len);  

//-- On attribut à "I" le numéro d'instance de la variable "NextInstance"
//   on incrémente "NextInstance" de 1
//   puis on affecte ce numéro au paramètre "Instance" passé par référence.
Instance I->Instance NextInstance++;

//-- Initialisation de la valeur des attributs de "I".
I->Header = NULL;

I->RecordList = NULL;
I->LastRecord = NULL;

I->Previous = NULL;
if ((I->Next = InstanceList) != NULL)
InstanceList->Previous = I;

//-- On fait pointer la liste des instances "InstanceList" sur l'instance "I".
InstanceList = I;

RS.SetText(" ");
return true;
}


Jusqu'ici les allocations en mémoire se passent bien... là où ça se plante c'est lors de l'appel à une deuxième fonction :

bool ACG_IMPORT WORD97_SetHeader(ObCharFld &RS,
 ObLongFld &Instance,
 ObCharFld &Header)
{
   Instance_s *I;
   int Len;

   I = FindInstance(Instance);
   if (!I) {
     MessageBox(NULL, "Instance WORD non trouvee", _TITRE_MSGBOX_ERREUR, MB_OK);
     RS.SetText("ERR");
     return false;
    }
   Len = strlen(Header.GetText()) + 1;
   I->Header = new char[Len];
   memcpy(I->Header, Header.GetText(), Len);
   RS.SetText(" ");
   return true;
}


et plus précisément lors de la ligne de code :

I->Header = new char[Len];


Quelqu'un aurait il une idée ?
D'avance merci.

Fred 
Afficher la suite 

5 réponses

Meilleure réponse
Messages postés
6
Date d'inscription
lundi 16 avril 2007
Statut
Membre
Dernière intervention
16 décembre 2010
3
Merci
Bonjour,

En fait le problème se situait dans une autre fonction où le pointeur newh était initialisé avec
newh = new char [len_newh]

mais dont l'espace mémoire n'était pas libérée...


bool ACG_IMPORT WORD97_ChangeString(ObCharFld &RS, ObCharFld &OldHeader, ObCharFld &OldSeparator, ObCharFld &NewHeader, ObCharFld &NewSeparator)
{
int len_olds;
int len_newh = 10240;
int len_news;
int n;

char *oldh = OldHeader.GetText();
char *olds = OldSeparator.GetText();
char *newh;
char news[128];

if (!Is_FCT_loaded(Convert))
Convert = (TConvert)GetProcAddress(word_hm, "Convert");
if (!Is_FCT_loaded_Msg(Convert))
return (false);

/* verification des parametres pour eviter un SEGVIO */
if (!NewSeparator.GetText() || 
!oldh || 
!olds || 
(len_olds strlen(olds)) 0 || 
(len_news Convert(news, NewSeparator.GetText())) 0 || 
strncmp(oldh, olds, len_olds)) {
RS.SetText("ERR");
return false;
}

oldh += len_olds; // suppression du separateur en debut de chaine

/* allocation d'une chaine pour le nouvel header */
newh = new char [len_newh];

n = 0; 
newh[n++] = '"';

while (*oldh) {
if (!strncmp(oldh, olds, len_olds)) {
/* C'est un separateur !
=> remplacer ce bazar par le nouveau separateur */
strcpy_s(&newh[n], len_newh, news); /* remplace par le nouveau separateur */

while (newh[n]) n++; /* se positionne a la fin */
oldh += len_olds; /* deplacement dans la chaine */

} else
/* C'est un caractere comme un autre */
newh[n++] = *oldh++;


/* petit test pour eviter que le buffer soit trop petit */
if (n >= len_newh - len_news - 1) {
char *tmp;
int new_len;

new_len = len_newh * 2;

tmp = new char [new_len];
memcpy(tmp, newh, len_newh);
delete newh; // dbg
newh = tmp;
len_newh = new_len;
}
}

/* fermeture du nouvel header */
newh[n++] = '"';
newh[n] = '\0';

        NewHeader.SetText(newh);

RS.SetText(" ");
return true;
}


Le problème est que la libération échoue après la commande
strcpy_s(&newh[n], len_newh, news)


J'ai donc remplacé tout ce code en utilisant la classe string qui est beaucoup plus sûre et demande moins de ligne de code...

Fred 

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 189 internautes nous ont dit merci ce mois-ci

Commenter la réponse de 3Fred9
Messages postés
180
Date d'inscription
mercredi 22 décembre 2004
Statut
Membre
Dernière intervention
16 août 2012
2
0
Merci
Salut,

Je dirais que FindInstance(...) échoue mais ne renvoie pas 0.
Un conseil : il faut toujours initialiser les pointeurs.
Avec "Instance_s *I = 0 ;", je pense que tu vas y voir plus clair.

Cordialement.
Commenter la réponse de cs_Lucky92
Messages postés
6
Date d'inscription
lundi 16 avril 2007
Statut
Membre
Dernière intervention
16 décembre 2010
0
Merci
Bonjour,

Tout d'abord merci Lucky92 pour cette première piste...

J'ai donc initialisé le pointeur I à 0 lors de sa déclaration dans la fonction SetHeader et ce avant l'appel à la fonction FindInstance comme tu m'a conseillé, mais celà n'a rien changé et la fonction FindInstance m'a bien retourné l'adresse du pointeur I crée dans la fonction NewInstance.

Affaire à suivre...

Encore merci.


Fred 
Commenter la réponse de 3Fred9
Messages postés
202
Date d'inscription
dimanche 18 mai 2003
Statut
Membre
Dernière intervention
6 mars 2010
0
Merci
salut,

0xFDFDFDFD veut dire que tu est en train de lire dans les guards du malloc. à mon avis FindInstance ne retourne pas le type que tu crois.

sinon en regardant vite fait le code:
cette ligne est très bizarre : "memset(I, 0, sizeof(I));" c'est pas plutot "memset(I, 0, sizeof(Instance_s));"
parceque la tu met à 0 que les 4 premiers octet.



Voili,Voilou
Commenter la réponse de mezaya
Messages postés
6
Date d'inscription
lundi 16 avril 2007
Statut
Membre
Dernière intervention
16 décembre 2010
0
Merci
Bonjour,

Encore merci mezaya pour cette piste. J'ai donc modifié l'allocation en mémoire de I comme cité... mais rien n'a changé...
Je rajoute le code de la fonction FindInstance afin d'y voir plus clair...

Instance_s *FindInstance(long I)
{
  Instance_s *Instance;
  for (Instance = InstanceList; Instance && (Instance->Instance != I); 
    Instance = Instance->Next);
  return Instance;
}


Encore merci pour votre aide...


Fred 
Commenter la réponse de 3Fred9