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

Résolu
3Fred9 Messages postés 6 Date d'inscription lundi 16 avril 2007 Statut Membre Dernière intervention 16 décembre 2010 - 1 mars 2010 à 13:13
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 

5 réponses

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,

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 
3
cs_Lucky92 Messages postés 180 Date d'inscription mercredi 22 décembre 2004 Statut Membre Dernière intervention 16 août 2012 2
1 mars 2010 à 21:14
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.
0
3Fred9 Messages postés 6 Date d'inscription lundi 16 avril 2007 Statut Membre Dernière intervention 16 décembre 2010
3 mars 2010 à 09:23
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 
0
mezaya Messages postés 202 Date d'inscription dimanche 18 mai 2003 Statut Membre Dernière intervention 6 mars 2010
6 mars 2010 à 14:22
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
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
3Fred9 Messages postés 6 Date d'inscription lundi 16 avril 2007 Statut Membre Dernière intervention 16 décembre 2010
9 mars 2010 à 07:50
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 
0
Rejoignez-nous