[gull] Subtilité de C n° 2 : type de retour de malloc

Leopoldo Ghielmetti leopoldo.ghielmetti at a3.epfl.ch
Fri Apr 4 09:50:59 CEST 2008


Je teste sur un pentium 4M et un pentium Core 2 Duo.

Il giorno gio, 03/04/2008 alle 17.20 +0200, Marc Mongenet ha scritto:
> Je me réponds à moi-même pour complèter mon message
> initial et clore cette subtilité n°2.
> NB : J'utilise gcc-3.3, car gcc 4 a une extension non standard
> qui reconnait malloc comme une fonction builtin, et donne des
> messages d'erreurs particuliers.
> 
> 
> Fichier f1.c (buggué !) :
> ------
> void f() { int *p = malloc(sizeof(int)); }
> ------
> marc> gcc-3.3 -c f1.c
> f1.c: Dans la fonction « f »:
> f1.c:1: attention : initialisation transforme un entier en pointeur
> sans transtypage
> marc>

J'ai eu:
cc -g    toto.c   -o toto
toto.c: In function ‘main’:
toto.c:1: warning: incompatible implicit declaration of built-in
function ‘malloc’
toto.c:1: warning: return type of ‘main’ is not ‘int’

sur le 32b et le 64b.
Note que j'ai du renommer f en main sinon ça ne pouvait pas compiler.

J'ai changé le code en:
void f()
{
  int *p = malloc(sizeof(int)); // <-- ici j'ai mis la fonction
  *p=43;
  printf("%p: %d\n", p, *p);
}

int main(int argc, char* argv[])
{
  f();
  return 0;
}

Juste pour lui faire faire quelque chose et j'ai:
# make toto
cc -g    toto.c   -o toto
toto.c: In function ‘f’:
toto.c:3: warning: incompatible implicit declaration of built-in
function ‘malloc’
toto.c:5: warning: incompatible implicit declaration of built-in
function ‘printf’
# ./toto
0x501010: 43

On est bien averti et le code tourne correctement (sur les deux
architectures).

La raison c'est que la fonction appelée est toujours la même malloc et
donc le résultat sera de toute façon correct.

La preuve c'est que si on regarde l'assembleur, le code généré est le
même que le include <stdlib.h> soit présent ou non.

Il y a en effet une légère différence dans le code généré en ce qui
concerne les labels.

> L'avertissement nous rattrape à la onzième heure.
> L'origine du problème est qu'on a oublié le #include<stdlib.h>.
> L'exécutable va probablement crasher sur architecture 64 bits.
> 
> 
> Fichier f2.c (buggué !) :
> ------
> void f() { int *p = (int*)malloc(sizeof(int)); }
> ------
> marc> gcc-3.3 -c f2.c
> marc>

Pareil, le code compile comme avant (avec les mêmes warnings) et le code
généré est le même que précédemment.

> Aucun avertissement ! C'est le danger de la méthode du cast
> explicite. Pourtant l'exécutable va probablement crasher sur
> architecture 64 bits, exactement pour la même raison que f1.c.
> 
> 
> Fichier f3.c (buggué !) :
> ------
> void f() { int *p = (int*)malloc(sizeof *p); }
> ------
> marc> gcc-3.3 -c f3.c
> marc>

Pareil, le code compile comme avant (avec les mêmes warnings) et le code
généré est le même que précédemment.

> Aucun avertissement ! C'est le danger de la méthode du cast
> explicite. Pourtant l'exécutable va probablement crasher sur
> architecture 64 bits, exactement pour la même raison que f1.c.
> 
> 
> Fichier f4.c (buggué !) :
> ------
> #include <stdlib.h>
> void f() { int *p = malloc(sizeof(short)); }
> ------
> marc> gcc-3.3 -c f4.c
> marc>

Après l'ajout des includes il n'y a plus le warning concernant le
malloc. Le code généré est le même mis à part la différence dans les
libellés.

Après compilation et application d'un beau strip j'obtiens exactement le
même exécutable que précédemment.

> Aucun avertissement ! C'est le danger de la méthode du cast
> implicite, car le compilateur ne remarque pas l'incohérence
> entre le int*p et le sizeof(short).

Donc il semblerait que peu importe s'il s'agit d'une architecture 32b ou
64b, les deux codes compilent correctement. Du moins avec le compilateur
gcc 4.1.2 sur architecture intel.

> Marc Mongenet

ciao, Leo




More information about the gull mailing list