Len Vs LenB - CopyMemory, Structures Perso (Types), etc.

Publié 16 juillet 09 04:26

Bonjour,


Titre barbare, j'en conviens. Ce post est là pour vous initier à la gestion mémoire effectuée par le compilateur de VB6.
Pour jouer avec les APIs, on a souvent à faire avec des UDTs (User Defined Types) du genre:

Type RECT 
   Left As Long 
   Top As Long 
   Right As Long 
   Bottom As Long
End Type

Et lorsque l'on joue en mémoire, on utilise bien souvent la longueur de la structure. On pourrait directement ici utiliser la valeur 16... mais pour des structures plus encapsulées, voir changeantes, il est plus sage de laisser à VB le soin de calculer la taille de la structure.

Lorsqu'on lit certains codes, on voit tantôt l'usage de Len, tantôt celui de LenB pour calculer cette taille.
Bien que ces deux instructions semblent toujours renvoyer la même valeur, il vaut mieux utiliser LenB.
 
En fait, VB aligne les champs des UDT sur 4 octets.

Conçu pour les architectures 32 bits, c'est l'octet qui est le plus petit élément adressable en mémoire, ce qui explique cette optimisation.
Len renvoie en réalité la taille cumulée des différents champs. LenB renvoie la taille prise en mémoire pour stocker la structure.
Prenons un exemple simple :


Private Type A 
    Start As Long 
    EquipementId As Long 
    End As Long 
    TblWordEquipementInData As Integer 
    FillByte As Byte 
End Type 

Private Sub Form_Load() 
Dim var As A 
    MsgBox Len(var)   => 15  donc la taille stricte des champs, additionnés 
    MsgBox LenB(var)  => 16  la taille reele de la structure 
End Sub 
 
là, la structure est optimisée en ce sens: les champs les lus grands en premiers 
en inversant simplement les champs, on obtiens: 

Private Type A 
    TblWordEquipementInData As Integer 
    Start As Long 
    EquipementId As Long 
    End As Long 
    FillByte As Byte 
End Type 

on à bien sur un Len de 15 
mais un LenB de 20 

après TblWordEquipementInData, VB laisse donc un trou de deux octets, pour pouvoir adresser directement Start 

ce qui nous fais bien 16 octets, plus 4 pour FillByte 
de même: 
Private Type A 
    TblWordEquipementInData As Integer 
    FillByte As Byte 
    FillByte2 As Byte 
    Start As Long 
    EquipementId As Long 
    End As Long 
End Type 

Donne un Len et un LenB égaux, de 16 puisque nous ne générons pas de trou. 

Un CopyMemory devra donc TOUJOURS voir un LenB utilisé, sous peine de manquer des infos, décalées pour alignement. 

Il faut également veiller a bien structurer les Types, pour miniser ce phénomène d'alignement.
Il ne reste plus qu'à se méfier des String, et tout est magnifique. Si vous voulez stocker du texte, privilégiez l'utilisation d'un tableau de Bytes...

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Commentaires

# ebartsoft said on juillet 16, 2009 23:15:

Oulala tu nous ressors des vieux cadavre :p

C'est plus vieux que moi ça...

# Renfield said on juillet 17, 2009 00:07:

J'en conviens. J'ai rédigé cela suite à une longue suite de messages sur le forum de VbFrance.

# rt15 said on juillet 17, 2009 16:39:

Salut,

"En fait, VB aligne les champs des UDT sur 4 octets."

Heu... Ca à l'air un peu plus compliqué que ça.

En effet, avec ta première structure, ça ferait :

Private Type A

   Start As Long (De 0 à 4)

   EquipementId As Long (De 4 à 8)

   End As Long (De 8 à 12)

   TblWordEquipementInData As Integer (De 12 à 16)

   FillByte As Byte (De 16 à ?)

End Type

Donc ça ferait forcément plus de 16, pourtant LenB renvoie 16.

L'explication est qu'il aligne les deux derniers champs sur 2 octets. Donc le processus du choix de l'alignement est plus compliqué que toujours 4 octets.

Private Type A

   TblWordEquipementInData As Integer

   Start As Long

   EquipementId As Long

   End As Long

   FillByte As Byte

End Type

Private Type B

   Start As Long

   EquipementId As Long

   End As Long

   TblWordEquipementInData As Integer

   FillByte As Byte

End Type

Private Sub Form_Load()

 Dim var As A

 Dim vbr As B

 Debug.Print "======================="

 Debug.Print "======================="

 Debug.Print VarPtr(var.TblWordEquipementInData) - VarPtr(var)

 Debug.Print VarPtr(var.Start) - VarPtr(var)

 Debug.Print VarPtr(var.EquipementId) - VarPtr(var)

 Debug.Print VarPtr(var.End) - VarPtr(var)

 Debug.Print VarPtr(var.FillByte) - VarPtr(var)

 Debug.Print LenB(var)

 Debug.Print "======================="

 Debug.Print VarPtr(vbr.Start) - VarPtr(vbr)

 Debug.Print VarPtr(vbr.EquipementId) - VarPtr(vbr)

 Debug.Print VarPtr(vbr.End) - VarPtr(vbr)

 Debug.Print VarPtr(vbr.TblWordEquipementInData) - VarPtr(vbr)

 Debug.Print VarPtr(vbr.FillByte) - VarPtr(vbr)

 Debug.Print LenB(vbr)

End Sub

# ebartsoft said on juillet 18, 2009 12:18:

rt15> l'alignement se fait sur la globalité de la structure.

un integer suivi d'un byte donnent 3 octets qui seront aligné avec un autre octet vide pour faire 4

dans ton exemple :

TblWordEquipementInData As Integer (De 12 à 13)

FillByte As Byte (De 13 à 14)

(alignement de 14 à 15)

@+

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Etendre le Team Web Access de TFS 2012 – Step 0 par Philippe Didiergeorges Aka Philess le 05-23-2013, 23:48

- Simuler facilement l’envoi de mail par Blog de Jérémy Jeanson le 05-22-2013, 12:52

- ProcDump 6.0 : support du filtrage sur messages d'exceptions .NET, des filtres multiples et du ciblage par nom de service par CoqBlog le 05-20-2013, 14:50

- Votez pour le TOP 10 des influenceurs SharePoint francophones ! par Le blog de Patrick [MVP SharePoint] le 05-20-2013, 12:59

- [Conf’SharePoint] Dernier rappel ! :-) par Le blog de Patrick [MVP SharePoint] le 05-20-2013, 09:09

- [ #SharePoint 2013 ] les modèles de sites standards… par Le blog de Patrick [MVP SharePoint] le 05-20-2013, 09:03

- 10 erreurs de compréhension concernant SharePoint… par Le blog de Patrick [MVP SharePoint] le 05-20-2013, 08:27

- Conf’SharePoint : 10 bonnes raisons pour ne pas la rater par Le petit blog de Pierre / Pierre's little blog le 05-14-2013, 02:24

- [Event] Soirée de lancement Agile .NET France à Lyon par Blog Agile/ALM de Vincent THAVONEKHAM le 05-13-2013, 01:29

- .NET / Debug : inspection de la mémoire d'applications .NET (dump ou processus live) : première livraison d'une librairie .NET par Microsoft par CoqBlog le 05-11-2013, 22:21




Ce blog

Abonnements