Organisation mémoire d'une structure

Le
Vincent
Bonjour,

Lors de l'utilisation d'une structure du type de celle ci-dessous,
est-ce qu'un élément de la norme prévois l'organisation exacte qu'elle
prendra en mémoire?

struct toto {
int a;
char nom[4];
int b;
};

Cette question me viens après avoir parcouru un bout de code venant de
PSDK. Cette fonction InitIcmpHeader(), de ce que j'en comprend, Affecte
à des endroits bien particulier d'un buffer, les information d'en-tête
nécessaire.

void InitIcmpHeader(char *buf, int datasize)
{
ICMP_HDR *icmp_hdr=NULL;
char *datapart=NULL;

icmp_hdr = (ICMP_HDR *)buf;
icmp_hdr->icmp_type = ICMPV4_ECHO_REQUEST_TYPE; //
request an ICMP echo
icmp_hdr->icmp_code = ICMPV4_ECHO_REQUEST_CODE;
icmp_hdr->icmp_id = (USHORT)GetCurrentProcessId();
icmp_hdr->icmp_checksum = 0;
icmp_hdr->icmp_sequence = 0;

datapart = buf + sizeof(ICMP_HDR);
//
// Place some data in the buffer.
//
memset(datapart, 'E', datasize);
}

J'en conclus, que les données membre de la structure doivent
impérativement être contigue en mémoire.

Me trompe-je?

VB
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Alexandre Bacquart
Le #19233691
Vincent wrote:
Bonjour,

Lors de l'utilisation d'une structure du type de celle ci-dessous,
est-ce qu'un élément de la norme prévois l'organisation exacte qu'elle
prendra en mémoire?



En aucun cas.

struct toto {
int a;
char nom[4];
int b;
};

Cette question me viens après avoir parcouru un bout de code venant de
PSDK. Cette fonction InitIcmpHeader(), de ce que j'en comprend, Affecte
à des endroits bien particulier d'un buffer, les information d'en-tête
nécessaire.

void InitIcmpHeader(char *buf, int datasize)
{
ICMP_HDR *icmp_hdr=NULL;
char *datapart=NULL;

icmp_hdr = (ICMP_HDR *)buf;
icmp_hdr->icmp_type = ICMPV4_ECHO_REQUEST_TYPE; //
request an ICMP echo
icmp_hdr->icmp_code = ICMPV4_ECHO_REQUEST_CODE;
icmp_hdr->icmp_id = (USHORT)GetCurrentProcessId();
icmp_hdr->icmp_checksum = 0;
icmp_hdr->icmp_sequence = 0;

datapart = buf + sizeof(ICMP_HDR);
//
// Place some data in the buffer.
//
memset(datapart, 'E', datasize);
}

J'en conclus, que les données membre de la structure doivent
impérativement être contigue en mémoire.



Pourquoi cette conclusion ? Le remplissage est effectué à travers un
pointeur de type ICMP_HDR. Aucun problème.

Par contre, le memset() opère sur le buffer *après* la place occupée par
ICMP_HDR, et les 'E' écrits ici seront contigus (il ne s'agit plus de
structure, mais d'un tableau de char).

Tout se passe comme prévu tant que la taille de buf est effectivement au
moins égale à sizeof(ICMP_HDR) + datasize.

Me trompe-je?



Vraisemblablement.


--
Alex
espie
Le #19234431
In article Vincent
Bonjour,

Lors de l'utilisation d'une structure du type de celle ci-dessous,
est-ce qu'un élément de la norme prévois l'organisation exacte qu'elle
prendra en mémoire?



Non, pas de facon portable.

struct toto {
int a;
char nom[4];
int b;
};



Tout ce que te dit la norme, c'est:
- les champs seront dans le meme ordre en memoire que dans ta structure.
- le premier champ est a la meme adresse que la structure elle-meme.

Pour le reste, c'est dependant de l'implementation. Il peut y avoir des
octets de bourrage qui s'inserent pour garantir l'alignement par exemple.
(typiquement, sur pas mal d'archi, un int doit avoir une adresse multiple
de 2 ou de 4, sinon, soit ca fait une bus-error, soit c'est pas du tout
efficace en pratique parce qu'il faut recuperer deux mots memoire au lieu
d'un.

Notons que ces octets de bourrage "n'existent pas" au niveau du langage,
ce qui fait que deux struct peuvent avoir les memes champs mais ne pas etre
identiques (au sens de memcmp).

i.e.,

#include struct p
{
char a;
int b;
};

int
f()
{
struct p v1, v2;

v1.a = 0; v1.b = 0;
v2.a = 0; v2.b = 0;
return memcmp(&v1, &v2, sizeof(v1));
}

a de fortes chances de renvoyer autre chose que 0...


Certains compilateurs te donnent des extensions (__packed,
__attribute__((__packed__)) ) qui peuvent enlever certains octet de bourrage,
mais ca n'a rien de portable, et c'est souvent sournois.


Cette question me viens après avoir parcouru un bout de code venant de
PSDK. Cette fonction InitIcmpHeader(), de ce que j'en comprend, Affecte
à des endroits bien particulier d'un buffer, les information d'en-tête
nécessaire.



Oui, c'est tres certainement du code non portable, et qui va avoir tendance
a dependre fortement, et de la plateforme, et du compilateur utilise.

Note: le langage te donne sizeof() pour savoir combien de place prend
ta structure en memoire (compte en char, sizeof(char) == 1 par definition),
et tu as eventuellement, offsetof(struct, champ) pour savoir ou se situe
un champ dans une structure.
Alexandre Bacquart
Le #19234541
Marc Espie wrote:
Cette question me viens après avoir parcouru un bout de code venant de
PSDK. Cette fonction InitIcmpHeader(), de ce que j'en comprend, Affecte
à des endroits bien particulier d'un buffer, les information d'en-tête
nécessaire.



Oui, c'est tres certainement du code non portable, et qui va avoir tendance
a dependre fortement, et de la plateforme, et du compilateur utilise.



Je conçois très bien que si l'appelant cherche ensuite à envoyer buf tel
quel sur un flux attendant une forme compacte, des problèmes puissent
survenir, mais j'ai du mal à voir en quoi le code de la fonction n'est
pas portable. Des précisions ?

--
Alex
espie
Le #19234601
In article Alexandre Bacquart
Marc Espie wrote:
Cette question me viens après avoir parcouru un bout de code venant de
PSDK. Cette fonction InitIcmpHeader(), de ce que j'en comprend, Affecte
à des endroits bien particulier d'un buffer, les information d'en-tête
nécessaire.







Oui, c'est tres certainement du code non portable, et qui va avoir tendance
a dependre fortement, et de la plateforme, et du compilateur utilise.





Je conçois très bien que si l'appelant cherche ensuite à envoyer buf tel
quel sur un flux attendant une forme compacte, des problèmes puissent
survenir, mais j'ai du mal à voir en quoi le code de la fonction n'est
pas portable. Des précisions ?



Ah, ta fonction elle-meme est portable. C'est ce qu'on en fait qui va souvent
ne pas l'etre, style envoyer directement ce contenu memoire sur ta carte
reseau.
Alexandre Bacquart
Le #19234641
Marc Espie wrote:
In article Alexandre Bacquart
Marc Espie wrote:
Cette question me viens après avoir parcouru un bout de code venant de
PSDK. Cette fonction InitIcmpHeader(), de ce que j'en comprend, Affecte
à des endroits bien particulier d'un buffer, les information d'en-tête
nécessaire.







Oui, c'est tres certainement du code non portable, et qui va avoir tendance
a dependre fortement, et de la plateforme, et du compilateur utilise.





Je conçois très bien que si l'appelant cherche ensuite à envoyer buf tel
quel sur un flux attendant une forme compacte, des problèmes puissent
survenir, mais j'ai du mal à voir en quoi le code de la fonction n'est
pas portable. Des précisions ?



Ah, ta fonction elle-meme est portable. C'est ce qu'on en fait qui va souvent
ne pas l'etre, style envoyer directement ce contenu memoire sur ta carte
reseau.



Nous sommes d'accord.


--
Alex
-ed-
Le #19235301
On 30 avr, 09:57, Vincent
Lors de l'utilisation d'une structure du type de celle ci-dessous,
est-ce qu'un élément de la norme prévois l'organisation exacte qu'e lle
prendra en mémoire?



Exacte, non. Tout ce que dit la norme, c'est que le premier élément de
la structure a la même adresse que la structure elle même, et que
l'ordre des éléments est celui indiqué dans la définition. Si on ve ut
connaitre l'emplacement relatif de chaque champ par rapport au
premier, on peut utiliser offsetof() qui est définie dans Cette macro indique la position en nombre de bytes. La valeur exacte
dépend de l'implémentation et ne peut être prévue.

Cette question me viens après avoir parcouru un bout de code venant de
PSDK. Cette fonction InitIcmpHeader(), de ce que j'en comprend, Affecte
à des endroits bien particulier d'un buffer, les information d'en-têt e
nécessaire.

void InitIcmpHeader(char *buf, int datasize)
{
     ICMP_HDR   *icmp_hdr=NULL;
     char       *datapart=NULL;

     icmp_hdr = (ICMP_HDR *)buf;
     icmp_hdr->icmp_type     = ICMPV4_ECHO_REQUEST_TYPE;        //
request an ICMP echo
     icmp_hdr->icmp_code     = ICMPV4_ECHO_REQUEST_CODE;
     icmp_hdr->icmp_id       = (USHORT)GetCurrentProcessId( );
     icmp_hdr->icmp_checksum = 0;
     icmp_hdr->icmp_sequence = 0;

     datapart = buf + sizeof(ICMP_HDR);
     //
     // Place some data in the buffer.
     //
     memset(datapart, 'E', datasize);

}

J'en conclus, que les données membre de la structure doivent
impérativement être contigue en mémoire.



Consécutives, oui. contiguë, non. Ce que tu voies est une
implémentation particulière. Ce n'est pas du code portable.
Antoine Leca
Le #19237131
Le 30/04/2009 22:48, Marc Espie écrivit :
In article
Lors de l'utilisation d'une structure du type de celle ci-dessous,
est-ce qu'un élément de la norme prévois l'organisation exacte qu'elle
prendra en mémoire?



Non, pas de facon portable.

Tout ce que te dit la norme, c'est:
- les champs seront dans le meme ordre en memoire que dans ta structure.
- le premier champ est a la meme adresse que la structure elle-meme.



- si on définit une autre structure, même avec un nom différent, mais
avec les mêmes définitions de membres (et le même compilateur, mêmes
options de compilation), alors l'organisation mémoire sera la même
pour les deux structures. Cela reste vrai (pour la partie commune,
évidemment) même si l'une des deux structures compte plus de membres


Antoine
espie
Le #19239651
In article Antoine Leca
Le 30/04/2009 22:48, Marc Espie écrivit :
In article
Lors de l'utilisation d'une structure du type de celle ci-dessous,
est-ce qu'un élément de la norme prévois l'organisation exacte qu'elle
prendra en mémoire?



Non, pas de facon portable.

Tout ce que te dit la norme, c'est:
- les champs seront dans le meme ordre en memoire que dans ta structure.
- le premier champ est a la meme adresse que la structure elle-meme.



- si on définit une autre structure, même avec un nom différent, mais
avec les mêmes définitions de membres (et le même compilateur, mêmes
options de compilation), alors l'organisation mémoire sera la même
pour les deux structures. Cela reste vrai (pour la partie commune,
évidemment) même si l'une des deux structures compte plus de membres



Oui, aussi ! je le sais, j'avais juste oublie de le mentionner. Sinon,
bon courage pour faire de l'objet avec heritage en C...
Publicité
Poster une réponse
Anonyme