C – pointeur à pointeur à la structure – erreur de segmentation

J’apprends les pointeurs C, alors j’ai essayé de créer un tableau de structures en utilisant la notation par pointeur J’atsortingbue un tableau de pointeurs à struct User , je définis des noms et des identifiants, puis j’essaie de l’imprimer, puis il se bloque.

Dockerfile:

 FROM ubuntu:xenial RUN apt-get update \ && apt-get install -y \ software-properties-common \ wget \ && add-apt-repository -y ppa:ubuntu-toolchain-r/test \ && apt-get update \ && apt-get install -y \ make \ git \ curl \ vim \ vim-gnome \ && apt-get install -y cmake=3.5.1-1ubuntu3 \ && apt-get install -y \ gcc-4.9 g++-4.9 gcc-4.9-base \ gcc-4.8 g++-4.8 gcc-4.8-base \ gcc-4.7 g++-4.7 gcc-4.7-base \ gcc-4.6 g++-4.6 gcc-4.6-base \ && update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 100 \ && update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 100 COPY ./*.c /tmp/ WORKDIR /tmp/ RUN gcc -Wall main.c -o main ENTRYPOINT ./main 

J’exécute mon programme dans le conteneur Docker parce que je veux avoir de la mémoire inutilisée.

Mon programme:

 #include  #include  #include  #define MAX_USERS_NUMBER 10 void set_users(); void print_users(); typedef struct User { int id; char* username; } User; User **users; int main(int argc, const char* argv[]) { set_users(); print_users(); return 0; } void set_users() { users = (User **) malloc(MAX_USERS_NUMBER * sizeof(User *)); int i; for (i = 0; i id = i; (*users + i)->username = (char *) malloc(strlen("username") + 1); strcpy((*users + i)->username, "username"); printf("%d. id: %d, username: %s\n", i, (*users + i)->id, (*users + i)->username); } } void print_users() { printf("\nUsers\n"); int i; for (i = 0; i id, (*users + i)->username); } } 

Je construis image par commande:

 docker build -t gcc-poc . 

Et je le lance par commande:

 docker run -it gcc-poc /bin/bash 

J’obtiens toujours le résultat:

 0. id: 0, username: username 1. id: 1, username: username 2. id: 2, username: username 3. id: 3, username: username 4. id: 4, username: username 5. id: 5, username: username 6. id: 6, username: username 7. id: 7, username: username 8. id: 8, username: username 9. id: 9, username: username Users 0. id: 0: ,username: 1. id: 1: ,username: username 2. id: 2: ,username: username 3. id: 3: ,username: username Segmentation fault 

J’ai lu le livre “Comprendre et utiliser les pointeurs C” de O’Reilly mais je ne peux pas en diagnostiquer la cause.

Puisque users est un pointeur sur un User , *(users + i) est un pointeur sur User et constitue l’arithmétique appropriée du pointeur. Mais (*users + i) n’est pas l’arithmétique de pointeur qui produira le résultat recherché.
Lorsqu’un pointeur est incrémenté, l’incrément sera la taille du type qu’il pointe. Par exemple ici:
users + 1 incrémentera les users avec sizeof(User *); Ce serait la taille d’un pointeur sur votre système.

Mais *users + 1 incrémentera *users avec sizeof(User) ; C’est la taille de la structure User vous avez définie.

Vous devez donc remplacer (*users + i) par (*(users + i)) dans le code. La paire de parenthèses supplémentaire est nécessaire car l’opérateur -> a une priorité plus élevée que l’opérateur * .

Modifiez vos fonctions set_users et print_users suivante:

 void set_users() { users = (User **) malloc(MAX_USERS_NUMBER * sizeof(User *)); int i; for (i = 0; i < MAX_USERS_NUMBER; i++) { *(users + i) = (User *) malloc(sizeof(User)); (*(users + i))->id = i; (*(users + i))->username = (char *) malloc(strlen("username") + 1); strcpy((*(users + i))->username, "username"); printf("%d. id: %d, username: %s\n", i, (*(users + i))->id, (*(users + i))->username); } } void print_users() { printf("\nUsers\n"); int i; for (i = 0; i < MAX_USERS_NUMBER; i++) { printf("%d. id: %d: ,username: %s\n", i, (*(users + i))->id, (*(users + i))->username); } } 

Essayez ceci:

 #define MAX_CHARS_USERNAME 40 void set_users() { static/*added*/ User* pUser; pUser = (User *) malloc(MAX_USERS_NUMBER * sizeof(User)); users = &pUser; int i; for (i = 0; i < MAX_USERS_NUMBER; i++) { (*users + i)->id = i; (*users + i)->username = (char *) malloc(MAX_CHARS_USERNAME); snprintf((*users + i)->username, MAX_CHARS_USERNAME, "username%d",i); printf("%d. id: %d, username: %s\n", i, (*users + i)->id, (*users + i)->username); } } 

Pour un pointeur à pointeur (si nécessaire), vous pouvez utiliser quelque chose comme ppUser . Et n’oubliez pas de libérer la mémoire (dans l’ordre inverse) après utilisation!