C

Un article de Haypo.

(Différences entre les versions)

Version du 4 juillet 2007 à 12:20

Retour à la page précédente Retour aux langages de programmation

Avertissement

Cet article est en cours de rédaction. Sa qualité est pauvre et son intérêt limité. Revenez un peu plus tard (ça peut être long), et lisez un autre article en attendant ;-) Si vous êtes impatient de lire la suite, secouez un peu son auteur :o)

« Il est dit que les programmeurs Lisp savent que
la gestion de la mémoire est si importante
qu'elle ne peut être laissée aux programmeurs,
et que les programmeurs C savent que
la gestion de la mémoire est si importante
qu'elle ne peut être laissée au système
 » — Bjarne Stroustrup

Le langage C, c'est de l'assembleur avec des fleurs tout autour.


Sommaire

Typage dangereux

Le C est un langage dangereux dans la déclaration des types de donnée et des conversions.

Problèmes :

  • on ne sait pas si le type char est signé ou non
  • la taille en bits d'un type (short, int, long) dépend du compilateur et de l'architecture
  • beaucoup de conversions dangereuses sont passées sous silence :
    • Conversion int <=> pointeur (void*) : pose des problèmes quand les deux types n'ont pas la même taille (ce qui arrive sur des processeurs 64-bit)
    • Mélange entier signé et entier non signé avec conversion silencieuse
    • Passage d'un entier signé à un entier signé plus grand

Illustration :

$ cat a.c
#include <stdio.h>
int main()
{
   char c = 250;
   unsigned int x = c;
   printf("c %%u=%u\n", c);
   printf("c %%i=%i\n", c);
   printf("x %%u=%u\n", x);
   return 0;
}

$ gcc a.c -o a -Wall -Wextra && ./a
c %u=4294967290
c %i=-6
x %u=4294967290

On copie 250 dans x et on obtient 4294967290. C'est plutôt gênant... Notez que gcc (4.1.2) n'affiche aucun avertissement.

Pointeurs dangereux

Autre danger en C : les pointeurs. Le langage autorise de lire et écrire n'importe où en mémoire. Or dans un système d'exploitation offrant une protection de la mémoire (utilisant une MMU), les accès illégaux génèrent un signal SIGSEGV qui est quasiment toujours fatal.

Pourtant, il est difficile voir impossible de se passer des pointeurs en C. Les langages Java et Python cachent les pointeurs mais ils existent toujours. Par contre, en Python il est impossible de faire un accès illégal en mémoire. Il sera sanctionné par une exception (LookupError sur un tableau, un dictionnaire ou une chaîne).

Au mieux, on peut vérifier les accès mémoire avec le programme Valgrind. Mais on ne pourra jamais garantir à 100% que tous les accès sont valides car on n'a pas de moyen formel de vérifier tous les cas d'utilisation d'un programme.

L'erreur la plus courante en C est le déreferrencement d'un pointeur nul. Exemple abrégé : « int *x = 0; printf("x=%i\n", *x); ». Il set souvent du au fait que la fonction malloc() peut échouer et que son code de retour n'est pas vérifie. Il vaut mieux utiliser une fonction plus haut niveau qui va générer une erreur dans le cas où malloc() échoue (retourne NULL). La fonction g_new() de la glib stoppe le programme avec abort() par exemple.

Articles connexes

Liens externes

Récupérée de « http://haypo.alwaysdata.net/wiki/C »