[C] Stockage tableau dans Mémoire partagée

Stockage tableau dans Mémoire partagée [C] - C - Programmation

Marsh Posté le 26-05-2008 à 11:55:56    

Bonjour à tous,
 
Pourriez vous m'eclairer & me dire pourquoi ceci ne fonctionne pas:

Code :
  1. define SIZEX 10
  2. define SIZEY 10
  3. ...
  4. shm_id = shmget(key, SIZEX*SIZEY, IPC_CREAT | SHM_R | SHM_W);
  5. map = (char **)shmat(shm_id, NULL, 0);
  6. map[0][1] = 't';
  7. map[0][2] = 'e';
  8. ...
  9. map[0][5] = '\0';
  10. shmdt(map);


 
alors que ceci fonctionne:

Code :
  1. define SIZEX 10
  2. define SIZEY 10
  3. ...
  4. shm_id = shmget(key, SIZEX*SIZEY, IPC_CREAT | SHM_R | SHM_W);
  5. map = (char **)shmat(shm_id, NULL, 0);
  6. for (i = 0; i < SIZEY; i++)
  7. {
  8.           map[i] = "blablabla\0";
  9. }
  10. shmdt(map);


 
Apparement quand j'essaye de manipuler case par case ca segfault (de même pr strcpy par exemple) mais quand je lui définie une valeur directement, cela fonctionne, c'est sans doute un problème de pointeur mais là j'avoue ne pas savoir quoi faire ?
 
Merci pour votre aide!

Reply

Marsh Posté le 26-05-2008 à 11:55:56   

Reply

Marsh Posté le 26-05-2008 à 11:59:32    

map n'est pas un char ** (pointeur sur pointeur)
 
 

Reply

Marsh Posté le 26-05-2008 à 12:41:48    

parce que t'es map[x] ne sont pas initialisés.

Reply

Marsh Posté le 26-05-2008 à 13:27:57    

Taz a écrit :

parce que t'es map[x] ne sont pas initialisés.


Bein meme si je les initialise de cette façon:

Code :
  1. 1. define SIZEX 10
  2.    2. define SIZEY 10
  3.    3. ...
  4.    4. shm_id = shmget(key, SIZEX*SIZEY, IPC_CREAT | SHM_R | SHM_W);
  5.    5. map = (char **)shmat(shm_id, NULL, 0);
  6.    6. for (i = 0; i < SIZEY; i++)
  7.    7. {
  8.    8.           map[i] = "blablabla\0";
  9.    9. }
  10.   10. shmdt(map);


 
et que ensuite je fasse:

Code :
  1. map[0][2] = 't';


Ca plante, pourtant en lecture ca passe nikel ??

Reply

Marsh Posté le 26-05-2008 à 13:33:18    

Taz a écrit :

parce que t'es map[x] ne sont pas initialisés.


ou ça, en fait ça dépends ce qu'il veut faire le monsieur  :jap:

Reply

Marsh Posté le 26-05-2008 à 13:34:51    

bjone a écrit :


ou ça, en fait ça dépends ce qu'il veut faire le monsieur  :jap:


bein moi je cherche juste à stocker des char dans un tableau, charactere par charactere ! :)

Reply

Marsh Posté le 26-05-2008 à 13:36:38    

moi ce qui me gène c'est ton SIZEX*SIZEY.
qu'est ce que tu veux faire, manipuler un tableau de char 2D, ou un tableau de pointeurs ?
si c'est un tableau de pointeurs char** est ok, mais la taille de la shm serait plustôt PTR_COUNT*sizeof( char* ).
 
autrement si tu comptes mettre en shm 10 chaines de 10 caractères max, tu te mets les pieds dans le tapis.

Reply

Marsh Posté le 26-05-2008 à 13:37:34    

Comment est déclarée ta variable map ?

Reply

Marsh Posté le 26-05-2008 à 13:38:49    

erasor2k5 a écrit :


bein moi je cherche juste à stocker des char dans un tableau, charactere par charactere ! :)


 
ok.
 
donc  
char *map;
et pas char **map;
 
for( i = 0; i < SIZEY; i++ )
{
    char *dst_string = map + SIZEX * i;
    strncpy( dst_string, "plouf", SIZEX );
}
 
et là tu as 10 (SIZEY) ploufs tous les 10 (SIZEX) char.

Message cité 1 fois
Message édité par bjone le 26-05-2008 à 13:41:37
Reply

Marsh Posté le 26-05-2008 à 13:39:52    

bjone a écrit :

autrement si tu comptes mettre en shm 10 chaines de 10 caractères max, tu te mets les pieds dans le tapis.


 
Oui moi c'est plutot ca que je veux faire, mon map est déclaré comme un -> char **map

Reply

Marsh Posté le 26-05-2008 à 13:39:52   

Reply

Marsh Posté le 26-05-2008 à 13:41:37    

bjone a écrit :


 
for( i = 0; i < SIZEY; i++ )
{
    char *dst_string = map + SIZEX * i;
    strcpy( dst_string, "plouf" );
}
 


 
Oui j'avais déja vu ca mais j'ai pas trop compri l'histoire, je vais pouvoir y acceder comme un tableau 2D après ?

Reply

Marsh Posté le 26-05-2008 à 13:46:05    

d'un point de vue déroulage mémoire, un tableau 2D est un tableau 1D ou les lignes sont les unes derrière les autres.
 
---
 
la confusion classique est qu'un "type **truc", c'est n'est pas un pointeur sur un tableau 2D, c'est un pointeur sur pointeur et du coup les offsets n'ont plus rien à voir.

Reply

Marsh Posté le 26-05-2008 à 13:48:01    

Oui je suis d'accord mai d'un point de vue technique est ce que je vais pouvoir le manipuler comme map[2][3], etc...après?

Reply

Marsh Posté le 26-05-2008 à 13:54:23    

oui et non :D
 
si tu déclares une fonction style:
 
void plop( char *ptr )
{
}
 
la taille de la ligne est "perdue", et il faut le faire à la main. style  
 
char plop( char *ptr, int x, int y )
{
   char *spot = ptr + x + y * SIZEX;
   return *spot;
}
 
par contre si tu déclares une fonction style:
 
char puick( char tab[SIZEY][SIZEX], int x, int y )
{
    return tab[y][x];
}
 
le compilo peut déterminer l'adresse correctement (si je me mets pas les pieds dans le tapis)
 
le problème étant que ça reste valide pour des dimensions statiques, mais si tu dois utiliser des dimensions variables cette approche tombe.

Reply

Marsh Posté le 26-05-2008 à 14:06:26    

Oui moi c'est statique, je défini la taille ds les define & j'y touche plus donc en principe ce serait ca pour moi...

bjone a écrit :

char puick( char tab[SIZEY][SIZEX], int x, int y )
{
    return tab[y][x];
}


 
C'est dingue quand même qu'il n'y ai aucun autre moyen de gerer ca c'est pas possible >_<
 
Ce que je comprend pas non plus c'est que pourtant quand je fait de la lecture char par char ca fonctionne

Code :
  1. int     display_map(char **map)
  2. {
  3.   int   x;
  4.   int   y;
  5.   for (y = 0; y < SIZEY; y++)
  6.     {
  7.       for (x = 0; x < SIZEX; x++)
  8. {
  9.           printf("%c ",map[y][x]);
  10.         }
  11.       printf("\n" );
  12.     }
  13. }


Donc je pointe forcément au bon endroit ? o_O  

Reply

Marsh Posté le 26-05-2008 à 14:09:10    

nan là tu vas mettre ton doigt dans le cul du diable :/

Reply

Marsh Posté le 26-05-2008 à 14:10:16    

t1 ca fait chier cette histoire quand même :/ foutu SHM :/  
Merci pour votre aide :))

Reply

Marsh Posté le 26-05-2008 à 14:19:06    

rien à voir avec les shm, ça a avoir avec l'adressage en C.
 
avec un **map comme déclaration de type,
 
un map[y][x], va chercher le y-ième (en fait +1 vu que le premier est le 0-ième) pointeur (de pointeur de char) à partir de map, puis à partir de cette adresse va chercher le x-ième pointeur.
 
avec un printf( "%c"  ), tu cast ce pointeur en en char pour l'afficher.
 
donc avoir un printf("%c ",map[y][x]), est encore plus faux que printf("%c ",*map[y][x])  
dans le premier tu affiche le pointeur casté en char, alors que dans le deuxième tu affiche un char.
 
mais vu que ton espace mémoire est en vrac, à la limite c'est moins pire. (le cul du diable ou ses laterines)
vu que map[y][x], va faire un seul accès mémoire débile (pour obtenir le pointeur [x], en supposant que le pointeur [y] soit dans l'espace de la shm)
alors que *map[y][x] te fera un double accès débile. (le pointeur[x] puis la déférence de ce pointeur pour obtenir le char de l'espace intersidéral)  
 
avec un char tab[SIZEY][SIZEX], le compilo fait ce que tu lui demande, il va chercher le char aux coordonnées x,y.

Message cité 1 fois
Message édité par bjone le 26-05-2008 à 14:22:32
Reply

Marsh Posté le 26-05-2008 à 14:22:59    

bjone a écrit :

rien à voir avec les shm, ça a avoir avec l'adressage en C.
 
avec un **map comme déclaration de type,
 
un map[y][x], va chercher le y-ième (en fait +1 vu que le premier est le 0-ième) pointeur (de pointeur de char) à partir de map, puis à partir de cette adresse va chercher le x-ième pointeur.
 
avec un printf( "%c"  ), tu cast ce pointeur en en char pour l'afficher.
 
donc avoir un printf("%c ",map[y][x]), est encore plus faux que printf("%c ",*map[y][x])  
dans le premier tu affiche le pointeur casté en char, alors que dans le deuxième tu affiche un char.
mais vu que ton l'espace mémoire est en vrac, à la limite c'est moins pire. (le cul du diable ou ses laterines)
 
avec un char tab[SIZEY][SIZEX], le compilo fait ce que tu lui demande, il va chercher le char aux coordonnées x,y.


 
Oui mais dans ce cas là je le déclare comment le tableau?

Code :
  1. char tab[SIZEY][SIZEX]
  2. void *addr;
  3. ...
  4. shm_id = shmget(key, SIZEX*SIZEY, IPC_CREAT | SHM_R | SHM_W);
  5. addr = shmat(shm_id, NULL, 0);
  6. ...
  7. tab[0][2] = 'x';
  8. tab[0][3] = 'x';
  9. ...
  10. addr = tab; ?? (ou memcpy(addr, tab, SIZEY*SIZEX))


Ca peut marcher?

Message cité 2 fois
Message édité par erasor2k5 le 26-05-2008 à 14:23:28
Reply

Marsh Posté le 26-05-2008 à 14:28:09    

t'as un problème de C là: . Travaille déjà à comment allouer une matrice avec un seul malloc. Ensuite tu transpose.
 
C'est moche cette histoire de * décalage.
 
Alloue N pointeurs + N x M x sizeof(Element).
Tu remplis les N pointeurs pour pointer vers le bon morceau à l'adresse i x M x sizeof(Element) et c'est bon. Après tu peux a[n][m];

Reply

Marsh Posté le 26-05-2008 à 14:32:04    

oki jvé essayer de voir ca !
 
Merci pr ton aide!

Reply

Marsh Posté le 26-05-2008 à 14:32:44    

erasor2k5 a écrit :


 
Oui mais dans ce cas là je le déclare comment le tableau?

Code :
  1. char tab[SIZEY][SIZEX]
  2. void *addr;
  3. ...
  4. shm_id = shmget(key, SIZEX*SIZEY, IPC_CREAT | SHM_R | SHM_W);
  5. addr = shmat(shm_id, NULL, 0);
  6. ...
  7. tab[0][2] = 'x';
  8. tab[0][3] = 'x';
  9. ...
  10. addr = tab; ?? (ou memcpy(addr, tab, SIZEY*SIZEX))


Ca peut marcher?


On à traiter 100x le cas d'allouer une matrice avec un seul malloc. Réfléchi un peu ou fais une recherche.

Reply

Marsh Posté le 26-05-2008 à 14:33:06    

erasor2k5 a écrit :


 
Oui mais dans ce cas là je le déclare comment le tableau?

Code :
  1. char tab[SIZEY][SIZEX]
  2. void *addr;
  3. ...
  4. shm_id = shmget(key, SIZEX*SIZEY, IPC_CREAT | SHM_R | SHM_W);
  5. addr = shmat(shm_id, NULL, 0);
  6. ...
  7. tab[0][2] = 'x';
  8. tab[0][3] = 'x';
  9. ...
  10. addr = tab; ?? (ou memcpy(addr, tab, SIZEY*SIZEX))


Ca peut marcher?


 
 
char *shm = shmat( ... )
process( shm );
 
avec:
 
void process( char tab[SIZEY][SIZEX] )
{
}
 

Reply

Marsh Posté le 26-05-2008 à 14:36:14    

Taz a écrit :

t'as un problème de C là: . Travaille déjà à comment allouer une matrice avec un seul malloc. Ensuite tu transpose.
 
C'est moche cette histoire de * décalage.
 
Alloue N pointeurs + N x M x sizeof(Element).
Tu remplis les N pointeurs pour pointer vers le bon morceau à l'adresse i x M x sizeof(Element) et c'est bon. Après tu peux a[n][m];


 
j'ai un peu peur qu'il se perde :)
de plus si les pointeurs sont dans la shm, il risque d'avoir des surprises.

Reply

Marsh Posté le 26-05-2008 à 14:38:31    

bjone a écrit :


 
j'ai un peu peur qu'il se perde :)
de plus si les pointeurs sont dans la shm, il risque d'avoir des surprises.


y a pas de raison. shm ou malloc c'est pareil. pas le peine de ce lancer dans des trucs compliqués si on ne maitrise pas.
d'ailleurs pour ce tableau de chaines, si la taille des chaines est fixe, c'est tout a fait possible de faire ça super simplement avec un pointer de char[N] et en allouer M.
 
Mais oui c'est les bases du C, pas la peine d'aller plus loin si on ne les a pas.

Reply

Marsh Posté le 26-05-2008 à 14:39:55    

Bein les malloc & tout j'ai aucun soucis, c'est juste la manipulation en mémoire qui est un peu plus nouvelle pour moi, je vais tester & voir !

Reply

Marsh Posté le 26-05-2008 à 14:42:16    

ce que je veux dire, c'est que le pointeur direct sur une ligne de matrice dans la shm, peut être invalide d'un process/binaire à un autre suivant où est projetée la shm dans l'espace d'adressage.  
donc un offset depuis le début de la shm oui, mais un pointeur absolu danger (dans le cas de la shm), ceci dit ça lui fera faire de l'exercice :D

Message cité 1 fois
Message édité par bjone le 26-05-2008 à 14:43:11
Reply

Marsh Posté le 26-05-2008 à 14:45:38    

bjone a écrit :

ce que je veux dire, c'est que le pointeur direct sur une ligne de matrice dans la shm, peut être invalide d'un process/binaire à un autre suivant où est projetée la shm dans l'espace d'adressage.  
donc un offset depuis le début de la shm oui, mais un pointeur absolu danger (dans le cas de la shm), ceci dit ça lui fera faire de l'exercice :D


c'est vrai. Vu qu'il faut bien allouer quelque chose pour que tout tienne en SHM, tes chaines sont à taille fixe. Ca se fait un un seul malloc
 

Code :
  1. #include <stdlib.h>
  2. enum { STRING_SIZE = 64 };
  3. typedef char (*STRING_ARRAY)[STRING_SIZE];
  4. STRING_ARRAY
  5. alloc(size_t n)
  6. {
  7.   return malloc(STRING_SIZE * n);
  8. }
  9. int main()
  10. {
  11.   STRING_ARRAY a = alloc(42);
  12.   return sizeof a[0];
  13. }

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed