01.05.2013 Views

C++ et éléments finis Note de cours de DEA (version provisoire)

C++ et éléments finis Note de cours de DEA (version provisoire)

C++ et éléments finis Note de cours de DEA (version provisoire)

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

10 CHAPITRE 1. QUELQUES ÉLÉMENTS DE SYNTAXE<br />

Il est fondamental <strong>de</strong> vérifier les bornes <strong>de</strong> tableaux, ainsi que les autres bornes connues. Aujourd’hui je<br />

viens <strong>de</strong> trouver une erreur stupi<strong>de</strong>, un déplacement <strong>de</strong> tableau dû à l’échange <strong>de</strong> 2 indices dans un tableau<br />

qui ralentissait très sensiblement mon logiciel (je n’avais respecté c<strong>et</strong>te régle).<br />

Exemple d’une p<strong>et</strong>ite classe qui mo<strong>de</strong>lise un tableau d’entier<br />

class Itab{ public:<br />

int n ;<br />

int *p ;<br />

Itab(int nn)<br />

{ n=nn) ;<br />

p=new int[n] ;<br />

assert(p) ;} // verification du pointeur<br />

˜Itab()<br />

{ assert(p) ; // verification du pointeur<br />

<strong>de</strong>l<strong>et</strong>e p ;<br />

p=0 ;} // pour eviter les doubles <strong>de</strong>struction<br />

int & operator[](int i) { assert( i >=0 && i < n && p ) ; r<strong>et</strong>urn p[i] ;}<br />

private: // la regle 1 : pas <strong>de</strong> copie par <strong>de</strong>faut il y a un <strong>de</strong>structeur<br />

Itab(const Itab &) ; // pas <strong>de</strong> constructeur par copie<br />

void operator=(const Itab &) ; // pas d’affection par copie<br />

}<br />

Régle 4 N’utiliser le macro générateur que si vous ne pouver par faire autrement, ou pour ajouter du co<strong>de</strong><br />

<strong>de</strong> verification ou test qui sera très utile lors <strong>de</strong> la mise au point.<br />

Régle 5 Une fois toutes les erreurs <strong>de</strong> compilation <strong>et</strong> d’édition <strong>de</strong>s liens corrigées, il faut éditer les liens en<br />

ajoutant CheckPtr.o (le purify du pauvre) à la liste <strong>de</strong>s obj<strong>et</strong>s à éditer les liens, afin <strong>de</strong> faire les vérifications<br />

<strong>de</strong>s allocations.<br />

Corriger tous les erreurs <strong>de</strong> pointeurs bien sûr, <strong>et</strong> les erreurs assertions avec le débogueur.<br />

1.3 Verificateur d’allocation<br />

L’idée est très simple, il suffit <strong>de</strong> surcharger les opérateurs new <strong>et</strong> <strong>de</strong>l<strong>et</strong>e, <strong>de</strong> stocker en mémoire tous les<br />

pointeurs alloués <strong>et</strong> <strong>de</strong> vérifier avant chaque déallacation s’il fut bien alloué (cf. AllocExtern::MyNewOperator(size t<br />

) <strong>et</strong> AllocExternData.MyDel<strong>et</strong>eOperator(void *). Le tout est d’encapsuler dans une classe AllocExtern<br />

pour qu’il n’y est pas <strong>de</strong> conflit <strong>de</strong> nom.<br />

De plus, on utilise malloc <strong>et</strong> free du C, pour éviter <strong>de</strong>s problèmes <strong>de</strong> récurrence infinie dans l’allocateur.<br />

Pour chaque allocation, avant <strong>et</strong> après le tableau, <strong>de</strong>ux p<strong>et</strong>ites zones mémoire <strong>de</strong> 8 oct<strong>et</strong>s sont utilisées pour<br />

r<strong>et</strong>rouver <strong>de</strong>s débor<strong>de</strong>ment amont <strong>et</strong> aval.<br />

Et le tout est initialisé <strong>et</strong> terminé sans modification du co<strong>de</strong> source en utilisant la variable AllocExternData<br />

globale qui est construite puis détruite. À la <strong>de</strong>struction la liste <strong>de</strong>s pointeurs non détruits est écrite dans<br />

un fichier, qui est relue à la construction, ce qui perm<strong>et</strong> <strong>de</strong> <strong>de</strong>boguer les oublis <strong>de</strong> déallocation <strong>de</strong> pointeurs.<br />

Remarque: Ce co<strong>de</strong> marche bien si l’on ne fait pas trop d’allocations, <strong>de</strong>structions dans le programme,<br />

car le nombre d’opérations pour vérifier la <strong>de</strong>struction d’un pointeur est en nombre <strong>de</strong> pointeurs alloués.<br />

L’algorithme est donc proportionnel au carré du nombre <strong>de</strong> pointeurs alloués par le programme. Il est possible<br />

d’améliorer l’algorithme en triant les pointeurs par adresse <strong>et</strong> en faisant une recherche dichotomique pour la<br />

<strong>de</strong>struction.<br />

Le source <strong>de</strong> ce vérificateur CheckPtr.cpp est disponible à l’adresse suivante FTP:CheckPtr.cpp. Pour l’utiliser,<br />

il suffit <strong>de</strong> compiler <strong>et</strong> d’éditer les liens avec les autres parties du programme.<br />

Il est aussi possible <strong>de</strong> r<strong>et</strong>rouver les pointeurs non désalloués, en utilisant votre déboguer favorit ( par exemple<br />

gdb ).<br />

Dans CheckPtr.cpp, il y a une macro du préprocesseur DEBUGUNALLOC qu’il faut <strong>de</strong>finir, <strong>et</strong> qui active l’appel <strong>de</strong><br />

la fonction <strong>de</strong>bugunalloc() à la création <strong>de</strong> chaque pointeur non détruit. La liste <strong>de</strong>s pointeurs non détruits<br />

est stockée dans le fichier ListOfUnAllocPtr.bin, <strong>et</strong> ce fichier est génére par l’exécution <strong>de</strong> votre programme.<br />

Donc pour déboguer votre programme, il suffit <strong>de</strong> faire:<br />

1. Compilez CheckPtr.cpp.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!