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

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

Votre réponse

5 réponses

Meilleure réponse
3Fred9 6 Messages postés lundi 16 avril 2007Date d'inscription 16 décembre 2010 Dernière intervention - 29 mars 2010 à 11:49
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 

Merci 3Fred9 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 69 internautes ce mois-ci

Commenter la réponse de 3Fred9
cs_Lucky92 180 Messages postés mercredi 22 décembre 2004Date d'inscription 16 août 2012 Dernière intervention - 1 mars 2010 à 21:14
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
3Fred9 6 Messages postés lundi 16 avril 2007Date d'inscription 16 décembre 2010 Dernière intervention - 3 mars 2010 à 09:23
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
mezaya 203 Messages postés dimanche 18 mai 2003Date d'inscription 6 mars 2010 Dernière intervention - 6 mars 2010 à 14:22
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
3Fred9 6 Messages postés lundi 16 avril 2007Date d'inscription 16 décembre 2010 Dernière intervention - 9 mars 2010 à 07:50
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

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.