<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Segmentation fault &#187; Applications</title>
	<atom:link href="http://www.segmentationfault.fr/categories/applications/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.segmentationfault.fr</link>
	<description>Projets d’un consultant en sécurité informatique</description>
	<lastBuildDate>Fri, 15 Feb 2019 08:02:10 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.2</generator>
		<item>
		<title>Release de XeeK v0.1b</title>
		<link>http://www.segmentationfault.fr/projets/release-de-xeek-v0-1b/</link>
		<comments>http://www.segmentationfault.fr/projets/release-de-xeek-v0-1b/#comments</comments>
		<pubDate>Sat, 19 Jun 2010 16:15:21 +0000</pubDate>
		<dc:creator>Emilien Girault</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[Nuit du hack]]></category>
		<category><![CDATA[Projets]]></category>
		<category><![CDATA[conférence]]></category>
		<category><![CDATA[hacking]]></category>
		<category><![CDATA[XeeK]]></category>

		<guid isPermaLink="false">http://www.segmentationfault.fr/?p=833</guid>
		<description><![CDATA[Comme promis, voici la toute première release de XeeK, en direct de la Nuit Du Hack 2010. Comme son numéro de version le suggère, il s&#8217;agit d&#8217;une version BETA donc potentiellement buggée . XeeK v0.1b : archive comportant le client, le serveur, ainsi que l&#8217;aide (fichiers INSTALL.txt et README.txt) Slides de la conférence (PDF) J&#8217;éditerai [...]]]></description>
			<content:encoded><![CDATA[<p>Comme promis, voici la toute première release de XeeK, en direct de la Nuit Du Hack 2010. Comme son numéro de version le suggère, il s&rsquo;agit d&rsquo;une version BETA donc potentiellement buggée <img src='http://www.segmentationfault.fr/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .<span id="more-833"></span></p>
<ul>
<li><a href="http://www.segmentationfault.fr/wp-content/uploads/2010/06/xeek-0.1b.zip">XeeK v0.1b</a> : archive comportant le client, le serveur, ainsi que l&rsquo;aide (fichiers INSTALL.txt et README.txt)</li>
<li><a href="http://www.segmentationfault.fr/wp-content/uploads/2010/06/XeeK.pdf">Slides de la conférence</a> (PDF)</li>
</ul>
<p>J&rsquo;éditerai ce billet prochainement pour y ajouter un petit tutorial concernant l&rsquo;installation et l&rsquo;utilisation de XeeK.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.segmentationfault.fr/projets/release-de-xeek-v0-1b/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Injecteur de fautes pour application distribuée</title>
		<link>http://www.segmentationfault.fr/projets/injecteur-fautes-parallele/</link>
		<comments>http://www.segmentationfault.fr/projets/injecteur-fautes-parallele/#comments</comments>
		<pubDate>Mon, 24 Mar 2008 13:10:43 +0000</pubDate>
		<dc:creator>Emilien Girault</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[Développement]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Projets]]></category>
		<category><![CDATA[Sécurité informatique]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[calcul distribué]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[projet]]></category>

		<guid isPermaLink="false">http://www.segmentationfault.fr/projets/injecteur-fautes-parallele/</guid>
		<description><![CDATA[Dans le cadre d&#8217;un projet scolaire, je travaille sur un projet concernant la sécurité des grilles de calcul. Rappelons qu&#8217;une grille de calcul désigne un ensemble d&#8217;ordinateurs interconnectés et qui ne sont pas nécessairement homogènes. Ce type d&#8217;architecture est utilisé majoritairement pour faire tourner des applications nécessitant une très grande puissance de calculs. Avec le [...]]]></description>
			<content:encoded><![CDATA[<p>Dans le cadre d&rsquo;un projet scolaire, je travaille sur un projet concernant la sécurité des grilles de calcul. Rappelons qu&rsquo;une grille de calcul désigne un ensemble d&rsquo;ordinateurs interconnectés et qui ne sont pas nécessairement homogènes. Ce type d&rsquo;architecture est utilisé majoritairement pour faire tourner des applications nécessitant une très grande puissance de calculs. Avec le temps, la taille de ces application tend à augmenter, donc les besoins en matière de sécurité également. Le but du projet sur lequel je travaille en ce moment est de concevoir un injecteur de fautes pour application distribuée. Cet injecteur doit permettre en quelque sorte de faire planter une application tournant en parallèle sur plusieurs machines, afin de mettre à l&rsquo;épreuve sa tolérance aux fautes. Ce billet présente rapidement l&rsquo;architecture de notre logiciel, qui est toujours en développement.</p>
<p>Pour concevoir une application parallèle, on utilise assez souvent la programmation par messages. Dans le cadre de notre projet, nous utilisons la bibliothèque <strong>LAM/MPI</strong> qui fournit toute une API permettant d&rsquo;envoyer des messages à des processus tournant sur des machines distantes. De plus, le but étant d&rsquo;injecter des fautes, nous avons choisit de provoquer ces fautes lors des envois et réceptions de messages. Ainsi nous pouvons facilement simuler aussi bien les pannes logicielles (déni de service) et matérielles (coupure de lien d&rsquo;un réseau, paquet perdu ou corrompu). Pour détourner les fonctions fournies par la bibliothèque LAM/MPI, nous utilisons la variable d&rsquo;environnement <strong>LD_PRELOAD</strong>. Cette variable des systèmes UNIX/Linux permet de charger dynamiquement une bibliothèque au lancement d&rsquo;une application. Le point intéressant est que cette bibliothèque peut redéfinir des fonctions qui existent déjà dans les autres bibliothèques, donc peut potentiellement les appeler tout en modifiant leur comportement.</p>
<p>LD_PRELOAD permet alors de modifier le comportement d&rsquo;une application tout en n&rsquo;ayant pas besoin de la recompiler ! Il est toutefois important de préciser que cette technique ne permet de détourner (<em>hooker</em>) que les fonctions définies dans des librairies dynamiques. C&rsquo;est un point crucial et qui nous a posé quelques problèmes. En effet nous utilisions au départ la librairie MPICH 1, et il se trouve que lorsqu&rsquo;une application est compilée avec, les appels MPI sont liés de manière statique. Un simple appel à la commande ldd permet de le voir. C&rsquo;est pourquoi nous avons choisis d&rsquo;utiliser LAM/MPI à la place.</p>
<p>Ainsi, nous avons développé une bibliothèque dynamique (fichier .so) dont le but est de venir d&rsquo;interposer entre l&rsquo;application parallèle et LAM/MPI. Cette bibliothèque (que nous avons nommé bibliothèque d&rsquo;interposition) redéfinit les fonctions MPI_Send() et MPI_Recv() en injectant des fautes comme des corruptions de données et des dénis de service. Les fautes ne sont pas générées de manière permanentes ; nous utilisons en plus un processus qui tourne en tâche de fond (démon) qui communique avec la librairie par l&rsquo;intermédiaire d&rsquo;un segment de mémoire partagé. Ce démon est en réalité un serveur utilisant CORBA. Son rôle est de rester en attente de requêtes et de dialoguer avec la librairie pour déclencher l&rsquo;injection de fautes. Il surveille également l&rsquo;application ainsi que le système par l&rsquo;intermédiaire de sondes logicielles afin de suivre en temps réel les valeurs de quelques variables, comme la charge CPU, l&rsquo;occupation mémoire, etc. Ces valeurs sont sauvegardées dans une base de données pour être retraitées plus tard par un module de statistiques.</p>
<p>Sur chaque machine tournent donc : une instance de l&rsquo;application distribuée, une instance de la bibliothèque d&rsquo;interposition, et une instance du démon. Mais en plus de tout cela, il faut être capable de déployer l&rsquo;application parallèle. Nous avons donc conçu un module dédié à cela, le simulateur. Il est contrôlable en ligne de commande ou via une interface graphique. Son but est de lancer l&rsquo;application parallèle, les démons et activer le détournement de fonction en exportant la variable LD_PRELOAD sur toutes les machines.</p>
<p>Ce projet, bien que relativement complexe, se révèle très intéressant. Cela nous a permis de découvrir et d&rsquo;utiliser des libraires et des technologies très utiles, comme CORBA, MPI, Boost, MySQL++. Nous utilisons également Flex et Bison pour la conception de l&rsquo;interpréteur de commandes du simulateur.</p>
<p>Au fut et à mesure du développement, je mettrai sans doute en ligne quelques billets exposant de façon plus détaillée la conception de certains des modules.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.segmentationfault.fr/projets/injecteur-fautes-parallele/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>#include is evil : Comment démêler un graphe d&#8217;inclusions en C++ ?</title>
		<link>http://www.segmentationfault.fr/applications/include-is-evil/</link>
		<comments>http://www.segmentationfault.fr/applications/include-is-evil/#comments</comments>
		<pubDate>Tue, 05 Feb 2008 13:46:15 +0000</pubDate>
		<dc:creator>Emilien Girault</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[Développement]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[développement]]></category>

		<guid isPermaLink="false">http://www.segmentationfault.fr/divers/include-is-evil/</guid>
		<description><![CDATA[Récemment, alors que je développais un projet C++ / OpenGL d&#8217;une ampleur relativement importante, j&#8217;ai du faire face à certains problèmes liés à l&#8217;utilisation du préprocesseur des langages C et C++. Qui ne connaît pas la directive #include ? Cette instruction bien que très pratique peut très vite devenir un véritable calvaire pour le développeur [...]]]></description>
			<content:encoded><![CDATA[<p>Récemment, alors que je développais <a href="dev/teapot-colony-wars/">un projet C++ / OpenGL</a> d&rsquo;une ampleur relativement importante, j&rsquo;ai du faire face à certains problèmes liés à l&rsquo;utilisation du préprocesseur des langages C et C++. Qui ne connaît pas la directive #include ? Cette instruction bien que très pratique peut très vite devenir un véritable calvaire pour le développeur lorsque le projet commence à prendre certaines proportions.</p>
<p>Ceux qui ont déjà eu des problèmes liés à #include savent de quoi je parle&#8230; Qu&rsquo;y a-t-il de plus énervant que de voir tout un projet se recompiler alors que l&rsquo;on vient juste de toucher à un seul fichier d&rsquo;en-tête ? J&rsquo;entends déjà certains me répondre sans hésiter : «Quand ça ne compile plus à cause d&rsquo;inclusions et de dépendances circulaires !», et ils ont probablement raison&#8230; Le but de ce billet est d&rsquo;illustrer les problèmes les plus courants que l&rsquo;on peut rencontrer en C++ et de proposer des solutions plus ou moins automatiques pour s&rsquo;en sortir. Je vais commencer par illustrer les problèmes de base et leurs solutions respectives, pour finalement converger vers une solution globale, comportant certaines règles à suivre qui permettent de résoudre les problèmes de ce style.  Notez que l&rsquo;approche de ce billet est progressive et que la solution  optimale est donnée à la fin.<span id="more-15"></span></p>
<p>En fait, après avoir été confronté à des problèmes de ce type et après avoir galéré à les résoudre, je me suis rendu compte que je ne maîtrisais pas comme il le fallait les actions du préprocesseur. Ce qui est plutôt gênant, quand arrivé à plusieurs milliers de lignes de code le projet refuse de compiler. En effet, dès que les projets atteignent une taille conséquente, la prise de tête peut rapidement commencer. Voici les principaux problèmes liés à l&rsquo;inclusion :</p>
<h3>Inclusion multiple</h3>
<p>Le premier type de problème se produit quand un fichier se retrouve inclus plusieurs fois. Il est tellement classique que tout le monde le connaît par coeur, et place donc des directives pour se protéger des inclusions multiples (les traditionnels #ifndef, #define et #endif). Je ne m&rsquo;éternise pas là dessus, j&rsquo;imagine que je ne vous apprends rien.</p>
<h3>Inclusion circulaire (agrégation, composition, utilisation&#8230;)</h3>
<p>Un problème plus vicieux peut néanmoins apparaître lorsqu&rsquo;un fichier se retrouve inclus avant un autre, ce dernier ayant besoin du premier. Ce genre de problème arrive lorsqu&rsquo;on déclare par exemple des classes possédant chacune une référence ou un pointeur vers l&rsquo;autre. Le compilateur étant par définition bête, il inclura comme il se doit les deux fichiers, mais inéluctablement, la définition d&rsquo;une classe se retrouvera avant celle de l&rsquo;autre. Et ça, le compilateur n&rsquo;aime pas, puisqu&rsquo;il tient absolument à ce que tous les symboles aient été déclarés à priori. Pour contourner ce genre de problèmes, on place simplement une directive non pas du préprocesseur, mais du langage C++ :</p>
<blockquote>
<pre>class MaClass;</pre>
</blockquote>
<p>Cette directive précise juste qu&rsquo;il sera question d&rsquo;une classe nommée MaClass dans la suite, et que le compilateur finira par trouver sa définition avant la fin de l&rsquo;analyse syntaxique. On nomme cette directive la &laquo;&nbsp;forward declaration&nbsp;&raquo;. Elle doit bien évidemment être placée <strong>avant</strong> chaque classe et doit être répétée autant de fois qu&rsquo;il le faut pour être certain que chaque symbole utilisé dans la définition de la classe ait bien été déclaré au préalable.</p>
<p>Il est important de noter que cette solution n&rsquo;est valable que lorsque l&rsquo;on utilisera des pointeurs ou des références sur des objets, qu&rsquo;ils soient des paramètres de méthodes ou des types de retours. Dans ces cas là, la directive #include n&rsquo;est même plus nécessaire. Ce point sera détaillé plus loin.</p>
<h3>Dépendance et inclusion circulaire</h3>
<p>Il s&rsquo;agit d&rsquo;un cas particulier de l&rsquo;inclusion circulaire que nous venons de voir, mais il faut comprendre qu&rsquo;il y a une nuance supplémentaire par rapport à la simple inclusion. Il y a en effet la notion de dépendance ; j&rsquo;entends par là qu&rsquo;une classe nécessite absolument la déclaration d&rsquo;une autre, et que cette déclaration doit avoir eu lieu <strong>avant</strong>. Dans le problème précédent, peu importe l&rsquo;ordre dans lequel le préprocesseur inclut les fichiers, l&rsquo;un sera placé avant l&rsquo;autre et cela ne gênera pas le compilateur. Cependant, il existe certains cas de force majeur, où le compilateur nécessite absolument la définition préalable d&rsquo;une classe ; c&rsquo;est notamment le cas de l&rsquo;<strong>héritage,</strong> mais également des <strong>constantes (#define) </strong>et des <strong>structures</strong>. Imaginez qu&rsquo;une classe B, définie dans un fichier B.h hérite d&rsquo;une classe A définie dans A.h. Naturellement, B.h inclut A.h, et cette inclusion est absolument nécessaire pour que le code soit compilable. Si vous aviez fait l&rsquo;inverse, c&rsquo;est à dire inclure B à partir de A, cela n&rsquo;aurais pas marché, même avec la directive &laquo;&nbsp;class&nbsp;&raquo;.</p>
<p>Supposez un instant que dans B.h vous ayez inclus le fichier A.h dans le bon sens, mais que A.h inclut un certain nombre de classes, chacune incluant une autre pour finalement former une chaîne d&rsquo;inclusion qui finirait par inclure B.h&#8230; Ce serait très gênant, car la compilation de B aurait beau aboutir, celle de A bloquerait. En effet, Lorsque le préprocesseur inspectera A.h en dépliant le code inclus par les #include, il finira par inclure B.h. Or B.h définit la classe B qui hérite de A&#8230; alors que la classe A n&rsquo;a finalement jamais été trouvée jusqu&rsquo;ici ! Et là, c&rsquo;est le drame&#8230;</p>
<p>Je n&rsquo;en vois que deux solutions pour se sortir de ce pétrin. La première, que je qualifierais de &laquo;&nbsp;pas propre&nbsp;&raquo; consiste à déporter le 1er #include gênant de A.h <strong>après</strong> la définition de la classe A ; autrement dit le mettre en fin de fichier. Cette solution est sale car non seulement elle oblige à séparer certaines directives ou inclusions qui doivent absolument être au début du fichier des autres qui posent problème. C&rsquo;est une solution qui peut marcher&#8230; Mais je pense que ce n&rsquo;est vraiment pas la bonne méthode à prendre, et qu&rsquo;elle risque même de reporter le problème à plus tard, quand le projet aura encore grandi et que la complexité du graphe d&rsquo;inclusions sera devenu inextricable. Je préfère nettement la 2ème que voici&#8230;</p>
<h3>LA solution</h3>
<p>Quelle est donc la solution miracle ? En fait, il s&rsquo;agit simplement de limiter au maximum les inclusions entre les fichiers d&rsquo;en-tête, en revenant aux principes de base de la compilation C/C++. Considérez un cas simple : A.cpp qui inclut A.h dans lequel se trouve la définition d&rsquo;une classe. Imaginez qu&rsquo;A.h nécessite d&rsquo;autres classes, qui sont incluses par A.h. Pour fixer les idées, nommons C.h un des fichiers inclus par A.h Finalement, A.cpp et A.h vont être compilés ensemble pour produire le même fichier objet ; il semble donc équivalent d&rsquo;inclure C.h à partir de A.h ou de A.cpp, puisque le résultat sera le même. Et pourtant, c&rsquo;est là que se situe toute la différence&#8230; En effet, si l&rsquo;on déplace le #include &laquo;&nbsp;C.h&nbsp;&raquo; de A.h dans A.cpp, on a réussi à éliminer une inclusion de A.h. Du coup, il faudra probablement mettre une directive &laquo;&nbsp;class C;&nbsp;&raquo; en tête de A.h, mais c&rsquo;est tout de même nettement mieux que d&rsquo;introduire une inclusion qui risque de provoquer des problèmes du style de ceux que l&rsquo;on vient de voir ! Ainsi, la règle à suivre est la suivante :</p>
<p><strong>Réduire au minimum vital les inclusions dans les fichiers d&rsquo;en-tête (.h) en les déportant dans les fichiers d&rsquo;implémentation (.cpp).</strong></p>
<p>C&rsquo;est une règle toute bête,mais qui simplifie énormément la vie lorsque l&rsquo;on développe un projet C ou C++. Le but est ainsi de supprimer le maximum (voire toutes) les directives #include des headers pour éviter les inclusions circulaires. Pour que cela compile, il sera nécessaire de rajouter les directives du type &laquo;&nbsp;class X;&nbsp;&raquo; en tête des fichiers d&rsquo;en-têtes, mais qu&rsquo;importe ! Ces directives sont &laquo;&nbsp;gratuites&nbsp;&raquo;, dans le sens où elles ne risquent pas d&rsquo;introduire des problèmes.</p>
<p>Concernant l&rsquo;héritage, nous avons vu qu&rsquo;il était absolument nécessaire qu&rsquo;une classe mère soit définie avant une de ses classes filles. C&rsquo;est pourquoi dans ce cas, on pourra se permettre de conserver la directive #include dans le fichier d&rsquo;en-tête, afin d&rsquo;éviter d&rsquo;avoir à inclure la classe mère dans chaque fichier .cpp utilisant cet en-tête. Mais à ma connaissance, c&rsquo;est le seul cas où la règle précédente ne s&rsquo;applique pas.</p>
<p>Et finalement, on s&rsquo;aperçoit que l&rsquo;on peut encore mieux faire, en élaguant au maximum le graphe d&rsquo;inclusions. En effet, il est possible de supprimer les inclusions de classes (qui se trouvent désormais dans les .cpp) lorsque la classe n&rsquo;est utilisée qu&rsquo;en tant que pointeur, référence, et qu&rsquo;aucune méthode n&rsquo;est utilisée. Autrement dit, si une classe A possède une méthode qui prend un paramètre un pointeur vers un objet de type B, et que cette méthode n&rsquo;utilise ni les méthodes ni les attributs de B, alors il n&rsquo;y a pas besoin d&rsquo;inclure B.h dans A.cpp. Un simple &laquo;&nbsp;class B;&nbsp;&raquo; suffira, et il sera du coup placé dans A.h vu que le prototype de la méthode y sera déclaré. Et en fait, c&rsquo;est tout à fait logique : si l&rsquo;on n&rsquo;utilise pas les membres de B, et qu&rsquo;il ne s&rsquo;agit que d&rsquo;un pointeur ou d&rsquo;une référence, le compilateur n&rsquo;a aucunement besoin de connaître la définition précise de B, puisque pointeurs et références occupent tous la même place en mémoire.</p>
<p>Pour résumer la méthode, voici la solution générale pour résoudre la grande majorité des problèmes d&rsquo;inclusions :</p>
<ul>
<li>Avant tout, chaque fichier d&rsquo;en-tête doit comporter les classique directives #ifndef, #define et #endif pour s&rsquo;assurer qu&rsquo;il ne sera pas inclus plusieurs fois.</li>
<li><strong>Aucune</strong> directive #include ne doit apparaître dans un .h, <strong>sauf</strong> si une de ces conditions est satisfaite :
<ul>
<li>ce fichier .h déclare une classe qui <strong>hérite</strong> d&rsquo;une autre classe</li>
<li>il nécessite la définition de <strong>constantes</strong> (au sens #define) ou de <strong>structures</strong> définies dans un autre .h.</li>
<li>la classe qu&rsquo;il déclare comporte comme attribut un objet d&rsquo;autre classe (et non pas un pointeur ou une référence vers celui-ci)</li>
</ul>
</li>
<li>Hormis ces 3 cas, il faut déporter les inclusions dans les fichiers .cpp.</li>
<li>Pour permettre la compilation du projet, il faut placer en tête des fichiers .h (avant la déclaration de la classe) autant de directives &laquo;&nbsp;class X;&nbsp;&raquo; que nécessaire, où X est le nom d&rsquo;une classe utilisée dans les méthodes du .h.</li>
<li>Si certaines méthodes d&rsquo;une classe A utilisent uniquement <strong>références</strong> ou des <strong>pointeurs</strong> sur des objets de type B, sans accéder aux membres (attributs ou méthodes) de B, il n&rsquo;est pas nécessaire de placer une directive #include dans A.cpp. Un simple &laquo;&nbsp;class B;&nbsp;&raquo; suffit dans A.h.</li>
</ul>
<p>En fait, on peut se souvenir simplement de ces règles en réfléchissant un minimum. Mettez-vous à la place d&rsquo;un compilateur : quelles informations vous faut-il pour pouvoir compiler une classe ? Comme un des rôles capitaux d&rsquo;un compilateur est d&rsquo;allouer la mémoire, il faut nécessairement toutes les informations concernant la taille des objets. Si un objet A agrège (contient) un objet de type B, on comprend facilement que la taille de l&rsquo;objet A sera calculée en fonction de la taille de B, donc l&rsquo;inclusion de la classe de B est inévitable. Idem pour les héritage. Mais quand il s&rsquo;agit de simples pointeurs et références, pas besoin de la définition complète, puisque tous les pointeurs et références occupent la même place en mémoire (celle du bus d&rsquo;adresse de la machine).</p>
<p>Au final, l&rsquo;application de cette méthode permet de démêler le graphe d&rsquo;inclusions de son projet de façon relativement simple et automatique. Il s&rsquo;agit de respecter ces règles de développement dans le but de limiter au maximum les dépendances entre fichiers. Les adeptes des gros projets savent combien il est pénible de voir tous les modules d&rsquo;un projet se recompiler lorsqu&rsquo;ils viennent de changer une constante dans un fichier d&rsquo;en-tête&#8230; Ce genre de problème est très souvent du à une mauvaise organisation des inclusions entre fichiers sources, ce qui induit une chaîne de dépendance énorme, provoquant la recompilation quasi-totale des sources. Dommage, quand on utilise les outils du style &laquo;&nbsp;Makefile&nbsp;&raquo; dont le but est justement de ne recompiler que ce qui est nécessaire.</p>
<p>J&rsquo;espère que cette technique permettra d&rsquo;en aider plus d&rsquo;un. En y réfléchissant, elle paraît évidente, mais l&rsquo;expérience montre le contraire&#8230; Une chose est sûre : si je l&rsquo;avais apprise dès le début, j&rsquo;aurais économisé un certain temps de débogage. Mais d&rsquo;un autre côté, le fait de s&rsquo;être arraché les cheveux dessus me garantit que je ne suis pas prêt de l&rsquo;oublier&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.segmentationfault.fr/applications/include-is-evil/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Teapot Colony Wars : Le premier simulateur de stratégies comportementales pour théières</title>
		<link>http://www.segmentationfault.fr/projets/teapot-colony-wars/</link>
		<comments>http://www.segmentationfault.fr/projets/teapot-colony-wars/#comments</comments>
		<pubDate>Mon, 04 Feb 2008 20:47:56 +0000</pubDate>
		<dc:creator>Emilien Girault</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[Développement]]></category>
		<category><![CDATA[Projets]]></category>
		<category><![CDATA[3D]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[projet]]></category>

		<guid isPermaLink="false">http://www.segmentationfault.fr/dev/teapot-colony-wars-le-premier-simulateur-de-strategies-comportementales-pour-theieres/</guid>
		<description><![CDATA[Dans le cadre de mes cours de programmation et de modélisation orientée objets, il nous a récemment été demandé de réaliser un projet en binôme. A vrai dire, nous l&#8217;avons rendu aujourd&#8217;hui&#8230; Le but était de modéliser et de concevoir une application simulant l&#8217;évolution de colonies d&#8217;individus sur un terrain. Le sujet décrivait les règles [...]]]></description>
			<content:encoded><![CDATA[<p>Dans le cadre de mes cours de programmation et de modélisation orientée objets, il nous a récemment  été demandé de réaliser un projet en binôme. A vrai dire, nous l&rsquo;avons rendu aujourd&rsquo;hui&#8230; Le but était de modéliser et de concevoir une application simulant l&rsquo;évolution de colonies d&rsquo;individus sur un terrain. Le sujet décrivait les règles de la simulation et de fonctionnement du monde dans lequel les colonies seraient amenées à évoluer. L&rsquo;objectif n&rsquo;était pas tant de coder une belle interface avec une intelligence artificielle hors du commun, mais plutôt de s&rsquo;attacher à bien concevoir l&rsquo;application, en utilisant les techniques habituelles comme le langage UML et les Designs Patterns.</p>
<p><img src="http://sourceforge.net/dbimage.php?id=158263" alt="Screenshot du projet" hspace="10" vspace="10" width="237" height="148" align="right" /></p>
<p>Avec un ami, nous avons eu une idée commune : tant qu&rsquo;à faire une application de simulation, autant se faire plaisir et la réaliser en 3D. Fans des technologies libres, nous avons donc choisi OpenGL et Glut. Nous avions tous les deux une petite expérience en OpenGL, pour ma part ce fut mon deuxième projet C++/OpenGL, bien que je trouve bien plus complexe que le 1er. Étant donné que nous n&rsquo;avions pas des talents d&rsquo;artistes, nous avons choisi de faire simple pour ce qui était de la représentation du monde et des individus. Les adeptes de Glut ou plus généralement de la 3D connaissent probablement la fameuse <a href="http://fr.wikipedia.org/wiki/Th%C3%A9i%C3%A8re_de_l'Utah">Théière de l&rsquo;Utah</a> utilisée dans un certain nombre d&rsquo;applications 3D. Ce modèle étant déjà présent par défaut dans la bibliothèque GLUT, nous avons décidé de l&rsquo;utiliser pour représenter les individus de nos colonies. Et nous en avons profité pour baptiser notre projet «Teapot Colony Wars».<span id="more-14"></span></p>
<p>Nous avions le choix du langage, et nous avons choisi le C++ non seulement pour sa rapidité, sa portabilité, mais aussi parce que nous souhaitions progresser dans ce domaine. Et tant qu&rsquo;à faire, nous l&rsquo;avons développé dans le but de le diffuser sous licence GPL 2, pour qu&rsquo;il continue à vivre et évoluer si certains veulent le reprendre. De plus, nous avons vraiment eu la volonté de développer un projet en nous rapprochant du monde professionnel, tout en n&rsquo;utilisant que des logiciels libres. Nous avons utilisé Subversion, un excellent outil de gestion de versions qui nous a bien simplifié la tâche pour le développement, ainsi que Doxygen, pour la génération de la documentation. Le rapport de conception a été réalisé en LaTeX, et la compilation de l&rsquo;exécutable a été grandement facilité par l&rsquo;emploi des Autotools (AutoConf, AutoMake, &#8230;).</p>
<p>Au final, Teapot Colony Wars, c&rsquo;est :</p>
<ul>
<li><strong> 96 fichiers sources</strong> (uniquement les .h et .cpp)</li>
<li>Un diagramme de <strong>45 classes</strong></li>
<li>Plus de <strong>9600 lignes</strong> de code C++</li>
<li>Un délai de <strong>6 semaines</strong> pour réaliser le projet (pendant lesquelles nous avons eu des examens&#8230;)</li>
<li>Plus de <strong>280 heures</strong> de travail</li>
<li><strong>268 révisions</strong> dans le dépot Subversion</li>
<li>Une documentation PDF de <strong>449 pages</strong> générée par Doxygen</li>
<li>Un rapport de <strong>28 pages</strong> décrivant la modélisation et nos choix conceptuels</li>
</ul>
<p>Nous avons profité de la livraison du projet pour publier la version 1 sur Sourceforge.net. Voici quelques unes des caractéristiques de l&rsquo;application :</p>
<ul>
<li>Le monde est composé de plusieurs colonies, chacune ayant sa couleur.</li>
<li>Chaque colonie peut créer des individus qui possèdent des caractéristiques propres comme sa taille. Une colonie consomme de la nourriture pour créer un individu.</li>
<li>Le monde est composé d&rsquo;une grille de cellules qui ont chacune des propriétés. Certaines sont inaccessibles (murs), d&rsquo;autres contiennent de la nourriture qui se renouvelle au fur et à mesure de la simulation (certaines sont à renouvellement instantané, mais pas d&rsquo;autres). Certaines cases sont des couloirs et inaccessibles aux individus trop grands.</li>
<li>Les individus évoluent selon certaines stratégies comportementales que la colonie leur impose. Leur but est de trouver de la nourriture et de la ramener à la colonie. Mais à chaque pas, un individu consomme de la nourriture proportionnellement à sa taille.</li>
<li>Chaque individu ne peut voir que les 8 cases adjacentes et a une très petite mémoire : il ne peut se souvenir que de la dernière case qu&rsquo;il a franchie. Mais pour l&rsquo;aider, il peut déposer des phéromones sur son passage. Chaque colonie définit ainsi 3 phéromones qui ne peuvent être comprises que par ses individus. Chaque phéromone a une durée de vie et se dégrade au fur et à mesure, jusqu&rsquo;à disparaître.</li>
<li>Quand deux individus ennemis se croisent, il y a combat. C&rsquo;est le plus fort qui gagne ! Le vainqueur peut alors se nourrir du cadavre de ses adversaires.</li>
<li>L&rsquo;utilisateur peut à sa guise faire une offrande en déposant une source de nourriture sur le terrain.</li>
<li>Il était demandé de tester deux stratégies différentes pour les individus. Les algorithmes heuristiques, qui peuvent être simples mais souvent imparfaits, et les algorithmes génétiques, consistant à définir des gènes pour les individus et effectuer un brassage génétique de la population en sélectionnant les meilleurs.</li>
</ul>
<p>Les commandes souris et clavier du simulateur sont les suivantes :</p>
<ul>
<li> Pavé numérique (4, 6 8, 2) : déplacements horizontaux et verticaux</li>
<li>Molette ou touches + et &#8211; : zoom</li>
<li>Maintien de Ctrl et défilement de la molette (ou + et -) : inclinaison verticale</li>
<li>Maintien de Ctrl + Clic gauche ou droit : rotation à gauche ou à droite</li>
<li>Espace : Activer / enlever le mode pause</li>
<li>Clic gauche : effectuer une itération</li>
<li>Étoile (*) : donner une offrande aux individus, qui apparaîtra sur le curseur de sélection (tore en bleu clair)</li>
</ul>
<p><img src="http://sourceforge.net/dbimage.php?id=158255" alt="Screenshot du projet" hspace="10" vspace="10" width="248" height="155" align="left" />Nous sommes globalement très satisfaits de ce projet, car nous avons pu finir dans les temps, même si nous aurions aimé rajouter quelques fonctionnalités supplémentaires. Mais cela restera tout à fait possible étant donné la grande extensibilité de notre application. En effet, grâce à un usage intensif de toutes les techniques propres à la modélisation orientée objet, comme le polymorphisme et les designs patterns, nous avons construit un ensemble de classes génériques, qui peuvent s&rsquo;apparenter à un framework. Il est ainsi tout à fait possible de rajouter à moindre coût des nouvelles cases, des nouveaux types d&rsquo;individus, changer leur représentation (pour ceux qui n&rsquo;aiment pas les théières&#8230;), changer le système de combat, et même pourquoi pas rajouter de nouveaux mouvements (comme le saut ou la téléportation).</p>
<p>Si cela vous intéresse, vous pouvez télécharger la version 1.0 du projet, tel que nous l&rsquo;avons rendu à nous professeurs. Les sources sont disponibles, ainsi que les exécutables pour Linux et Windows. Attention toutefois pour ce dernier, il semble que la portabilité soit encore un tout petit peu imparfaite ; en effet nous n&rsquo;avons pas encore eu le temps de changer quelques détails qui peuvent bloquer la génération de l&rsquo;exécutable selon le compilateur utilisé. Mais nous allons bientôt remédier à cela&#8230;</p>
<p>Voici les liens pour accéder aux ressources du projet :</p>
<ul>
<li><a href="http://sourceforge.net/projects/colonywars/">Site du projet sur Sourceforge.net</a></li>
<li><a href="http://sourceforge.net/project/showfiles.php?group_id=213004">La page de téléchargement</a></li>
<li><a href="http://colonywars.svn.sourceforge.net/viewvc/colonywars/">Le dépot SVN accessible en ligne</a></li>
<li><a href="http://sourceforge.net/svn/?group_id=213004">Les détails pour effectuer un check-out du SVN</a></li>
<li><a href="http://colonywars.sourceforge.net/doc/">La documentation HTML en ligne</a></li>
</ul>
<p>Pour lancer l&rsquo;application sous Windows, vous avez juste à lancer l&rsquo;exécutable. Sous Linux, pensez toutefois à lancer l&rsquo;application en mode console pour éviter les surprises ; en effet, il faut que le dossier de textures se trouve dans le dossier courant.</p>
<p>Pour compiler le projet sous Linux, assurez-vous de disposer des bibliothèques pour le développement d&rsquo;application graphiques, en particulier Glut. Décompressez l&rsquo;archive dans un répertoire, puis tapez les instructions suivantes :</p>
<blockquote>
<pre>$ ./configure --prefix=$HOME</pre>
<pre>$ make</pre>
<pre>$ make install</pre>
</blockquote>
<p>L&rsquo;application s&rsquo;installera automatiquement dans votre homedir, dans le dossier bin. Si la documentation vous tente, vous pouvez générer le HTML et les fichiers LaTeX en tapant :</p>
<blockquote>
<pre>$ doxygen Doxyfile</pre>
</blockquote>
<p>Ensuite, placez-vous dans le dossier doc/latex et tapez simplement :</p>
<blockquote>
<pre>$ make</pre>
</blockquote>
<p>Le PDF résultat se nomme  «refman.pdf» et sera généré dans le dossier courant. Bonne lecture&#8230;</p>
<p>Un site internet du projet verra peut-être le jour au courant de l&rsquo;année, si je trouve un peu de temps à y consacrer. N&rsquo;hésitez pas à me faire part de tous vos commentaires sur ce projet. Profitez de sa licence et faites le vivre !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.segmentationfault.fr/projets/teapot-colony-wars/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
