2017-06-08 1 views
1

Je reçois l'échec de vérification d'exécution # 2 - Empiler autour de la variable 'obj' était une erreur corrompue lorsque j'ai exécuté le code suivant. Je sais que cela échoue à cause de l'écrasement des limites de 'obj', provoquant la corruption de la pile. Alors, comment empêcher le dépassement de tampon ici.Échec de vérification d'exécution # 2 - La pile autour de la variable 'obj' était corrompue

typedef struct _INFO { 
    int Count; 
} Info, *InfoPtr; 

#define MAX_COUNT    10 

//void fn(Info(*obj)[MAX_COUNT]) 
void fn(Info (*obj)[MAX_COUNT]) 
{ 
    for (int i = 0; i < 2; i++) 
    { 
     obj[i]->Count = i; 
    } 
} 

int main() 
{ 
    Info obj[MAX_COUNT]; 
    fn(&obj); 
    return 1; 
} 
+0

Modifiez ce '(Info (* obj) [MAX_COUNT])' -> '(taille size_t, Info obj [taille])'. – Lundin

+0

la séquence «_L» (soulignement suivi de la majuscule) est «réservée» par le système, de sorte que de telles séquences ne doivent pas être utilisées dans le code utilisateur. – user3629249

Répondre

5

Avec Info (*obj)[MAX_COUNT] vous dire que obj est un pointeur sur un tableau de MAX_COUNT objets de type Info.

Mais vous l'utiliser comme obj[i]->Count = i qui traite obj comme un tableau de pointeurs à Info objets. C'est à dire. Info *obj][]. Pas la même chose. Et cela conduit à undefined comportement.

La solution est assez simple, ne passez pas un pointeur sur le tableau comme argument, et traitez-le comme un tableau d'objets et non de pointeurs vers des objets.

à savoir

typedef struct Info { 
    int Count; 
} Info; 

#define MAX_COUNT    10 

void fn(Info *obj, const size_t elems) 
{ 
    for (size_t i = 0; i < elems; i++) 
    { 
     obj[i].Count = i; 
    } 
} 

int main() 
{ 
    Info obj[MAX_COUNT]; 
    fn(obj, MAX_COUNT); 
} 

Les changements sont notamment la déclaration de fonction fn, qui prend un pointeur à Info. C'est parce que les tableaux se désintègrent naturellement en pointeurs vers leur premier élément. J'ai également ajouté un argument pour contenir le nombre d'éléments dans le tableau, donc la fonction le connaît. Cela rend la fonction plus générale et vous pouvez lui passer différents tableaux de différentes tailles.

J'ai aussi changé à main pour ne rien retourner du tout. Depuis le standard C99 une fonction main sans return explicite obtiendra implicitement un return 0 par le compilateur. Et le retour 0 de la fonction main est généralement considéré comme "OK" ou "pas d'échec". Renvoyer une valeur non nulle est considéré comme un échec ou une erreur.

J'ai également changé le nom de votre structure. Les noms (C ou préprocesseur) avec un soulignement principal suivi d'une lettre majuscule sont réservés dans toutes les étendues par le compilateur et la bibliothèque C standard. En outre, les noms de balise de structure résident dans un espace de noms distinct, vous pouvez donc avoir le même nom de structure que le nom de type (alias de type, tel que défini par typedef). J'ai également supprimé le nom de type InfoPtr, en utilisant de tels pointeurs que les noms de type obfuscates le code et le rend moins lisible et maintenable.