Ne pas faire de référence externe à un tableau avec un pointeur en C

Tout ou presque est dans le titre. Lorsque vous codez en C, vous pouvez être tenté de déclarer / définir dans un fichier un tableau et d’y faire référence dans un autre fichier C en utilisant un pointeur au lieu d’un tableau. C’est vrai qu’en C, un pointeur, un tableau, c’est presque pareil, mais ce n’est pas la même chose (j’avais déjà écrit sur le sujet : https://gradot.wordpress.com/2012/08/08/de-la-difference-entre-tableaux-et-pointeurs-en-c/). Ce qui est très embêtant, c’est que l’édition des liens se fait mais la valeur du pointeur n’est pas l’adresse du tableau qu’on pense référencer mais la valeur formée par les 4 premiers bytes de ce tableaux (4 ou plus probablement la taille d’un pointeur sur l’architecture cible). Un exemple est toujours plus parlant, en voilà un.

Dans un fichier definitions.c, on crée deux tableaux :

int with_array[4096] = {0x51};
int with_pointer[4096] = {0x42};

Dans un fichier main.c, on fait une référence à ces tableaux de deux manières différentes :

#include "stdio.h"
extern int with_array[];
extern int* with_pointer;

int main(void)
{
    printf("%p\n", with_array);
    printf("%X\n", with_array[0]);
    // printf("%u\n", sizeof with_array); // impossible because 'with_array' is declared as an incomplete type

    printf("%p\n", with_pointer);
    printf("%X\n", *with_pointer); // will very likely cause a segmentation fault because we cannot read memory at with address
}

Je compile le tout avec MinGW et je n’obtiens pas d’erreur ni de warning. J’exécute le programme sous Windows 7 et j’obtiens :

00407000
51
00000042

Suivi de près par une erreur de segmentation.

Lors de la déclaration externe avec with_pointer, il s’agit « vraiment » du tableau et non d’un cast implicite en un pointeur vers le premier élément du tableau. Lors de l’édition des liens, il n’y a pas de vérification de type et le linker trouve en mémoire la valeur 42, à l’adresse correspondant à with_pointer. Comme il est très probable qu’on ne puisse pas accéder tranquillement à l’adresse 42, on obtient une erreur de segmentation.

Publicités

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s