Pointeurs à l’intérieur du segment de mémoire partagée

J’ai essayé cela pendant des heures, et google toutes les choses auxquelles je pense, mais je deviens fou.

J’ai un struct:

typedef struct { int rows; int collumns; int* mat; char* IDs_row; } mem; 

Je ne connais pas les tailles des int * (une masortingce) et des char * jusqu’à plus tard.

Quand je le fais, je crée la mémoire partagée comme ceci:

 mem *ctrl; int size = (2 + ((i-1)*num_cons))*sizeof(int) + i*26*sizeof(char); //I have the real size now shmemid = shmget(KEY, size, IPC_CREAT | 0666); if (shmemid < 0) { perror("Ha fallado la creacion de la memoria compartida."); exit(1); } ctrl = (mem *)shmat(shmemid, 0, 0); if (ctrl <= (mem *)(0)) { perror("Ha fallado el acceso a memoria compartida"); exit(2); } 

Pas de problème ici. Ensuite, je donne une valeur à ctrl-> lignes et colonnes et atsortingbue 0 à toute la masortingce.

Mais après cela, j’écris quelque chose dans la faute de segmentation char * et bam.

Déboguant le programme, j’ai vu que les deux pointeurs, mat et IDs_row étaient null. Comment leur donner les valeurs correctes dans le segment de mémoire partagée?

J’ai essayé de supprimer le pointeur char *, juste pour l’essayer, puis l’erreur de segmentation se trouvait dans l’autre programme connecté à la mémoire partagée et vérifiait simplement les valeurs dans la masortingce (vérification -> lignes et -> les colonnes étaient succesfull)

 ctrl = (mem *)shmat(shmemid, 0, 0); 

Cela n’affecte que la mémoire valide au pointeur ctrl , pas à ctrl->mat ou ctrl->IDs_row .

Vous voulez probablement:

 mem *ctrl; shmemid = shmget(KEY, sizeof(ctrl), IPC_CREAT | 0666); //allocate memory for the structure ctrl = (mem *)shmat(shmemid, 0, 0); //allocate memory for the int* shmemid = shmget(KEY,((i-1)*num_cons))*sizeof(int), IPC_CREAT | 0666); ctrl->mat = (int*)shmat(shmemid, 0, 0); //allocate memory for the char* shmemid = shmget(KEY,i*26*sizeof(char), IPC_CREAT | 0666); ctrl->IDs_row = (char*)shmat(shmemid,0,0); 

Tout d’abord, mettre des pointeurs absolus dans des segments de mémoire partagée est une idée terrifiante – ces indications ne seraient valides que dans le processus qui remplissait leurs valeurs. Les segments de mémoire partagée ne sont pas garantis pour se connecter à la même adresse virtuelle dans chaque processus. Au contraire – ils attachent l’endroit où le système le juge possible lorsque shmaddr == NULL est spécifié à l’appel de shmat() . Vous pouvez spécifier la même adresse virtuelle lors de l’appel de shmat() mais vous devez vous assurer que rien d’autre n’est mappé sur cette région mémoire dans tous les processus participants. C’est difficile à faire de manière portable. Ce que vous aimeriez le plus, c’est soit:

1) Allouer un grand segment de mémoire partagée qui accueille à la fois la structure mem et les deux tableaux de données. Ensuite, vous ne devez pas mettre de pointeurs absolus, mais plutôt des pointeurs par rapport au début du bloc de mémoire, puis ajuster votre utilisation.

2) Allouez trois segments de mémoire partagée différents mais, au lieu de placer des pointeurs , placez les ID de mémoire partagée tels qu’ils sont renvoyés par shmget() :

 typedef struct { int rows; int collumns; int mat_id; int IDs_row_id; } mem; 

Lorsque vous avez besoin d’accéder à la masortingce ou au tableau IDs, attachez-le simplement à l’identifiant de la mémoire partagée stocké dans le champ correspondant.

Faites attention si l’utilisation de la même KEY dans les shmget() suivants de shmget() ne produira pas le résultat attendu à moins que KEY == IPC_PRIVATE . Il est préférable d’utiliser une valeur de clé fixe pour le bloc de mémoire partagée avec le descripteur (de type mem ) et IPC_PRIVATE pour les deux autres blocs de mémoire, sinon les trois appels IPC_PRIVATE réellement le même bloc de mémoire partagée. et les deux suivants renverront simplement son identifiant car un bloc avec cette clé existe déjà.