Adresse Mémoire d'une variable VB (pour les pros de l'API)
jockos
Messages postés321Date d'inscriptiondimanche 22 octobre 2000StatutMembreDernière intervention14 mai 2005
-
19 févr. 2004 à 10:46
jockos
Messages postés321Date d'inscriptiondimanche 22 octobre 2000StatutMembreDernière intervention14 mai 2005
-
24 févr. 2004 à 17:24
Bonjour,
J'aimerais pourvoir choisir moi même l'adresse mémoire d'une variable VB. Le VB ne gérant pas les pointeurs, je me doute qu'il faut passer par une API.
Mais laquelle ?
Je sais récupérer l'adresse d'une variable VB avec "l'API" native (situé dans le runtime VB) StrPtr(str as String) as Long
Mais je voudrais pouvoir choisir moi même l'adresse d'une variable (en gros faire une allocation mémoire).
Ceci dans le but de partager une zone mémoire par plusieurs variables VB. (pointeurs)
Merci pour votre aide...
A voir également:
"Php version 4.4.5" "build date" "server api" "php variables"
crenaud76
Messages postés4172Date d'inscriptionmercredi 30 juillet 2003StatutMembreDernière intervention 9 juin 200628 19 févr. 2004 à 11:12
Tu as l'API GlobalAlloc() qui alloue une quantité de mémoire sur le Tas .. Avec GlobalFree() pour libérer bien sur, sinon, tu cours au crash de Windows
jockos
Messages postés321Date d'inscriptiondimanche 22 octobre 2000StatutMembreDernière intervention14 mai 20052 19 févr. 2004 à 11:23
Il vaut mieux utiliser HeapAlloc ou VirtualAlloc en fonction des quantités de mémoires à allouer.
GlobalAlloc est obsolete.
Merci quand même, mais ça ne répond pas du tout à ma question...
Ma question est très simple (et prend 2 lignes de code en C/C++ ou autre langage utilisant les pointeurs) mais très dur à réaliser en VB :
Comment déclarer 2 variables (ou plus) de type String (par exemple) utilisant le même emplacement mémoire ?
On peut tourner la question différemment, mais ça revient au même...
Comment faire pointer 2 variables String sur la même zone mémoire.
Dim hHeap As Long
Dim pointer as Long 'Pointeur sur la zone mémoire
Dim lenString as long 'Taille de ma String
'Comment déclarer 2 string (str1 et str2) qui vont pointer sur le buffer de 500 octets à l'adresse mémoire pointer ?
HeapFree GetProcessHeap(), 0, ptr
Bref, je pense que tu as compris le problème...
ça permettrait d'optimiser la rapidité d'un programme VB de manière considérable car le programme occuperait beaucoup moins de mémoire en RAM et n'aurait pas à allouer de la mémoire à chaque fois.
jockos
Messages postés321Date d'inscriptiondimanche 22 octobre 2000StatutMembreDernière intervention14 mai 20052 19 févr. 2004 à 11:24
Il vaut mieux utiliser HeapAlloc ou VirtualAlloc en fonction des quantités de mémoires à allouer.
GlobalAlloc est obsolete.
Merci quand même, mais ça ne répond pas du tout à ma question...
Ma question est très simple (et prend 2 lignes de code en C/C++ ou autre langage utilisant les pointeurs) mais très dur à réaliser en VB :
Comment déclarer 2 variables (ou plus) de type String (par exemple) utilisant le même emplacement mémoire ?
On peut tourner la question différemment, mais ça revient au même...
Comment faire pointer 2 variables String sur la même zone mémoire.
Dim hHeap As Long
Dim pointer as Long 'Pointeur sur la zone mémoire
Dim lenString as long 'Taille de ma String
'Comment déclarer 2 string (str1 et str2) qui vont pointer sur le buffer de 500 octets à l'adresse mémoire pointer ?
HeapFree GetProcessHeap(), 0, pointer
Bref, je pense que tu as compris le problème...
ça permettrait d'optimiser la rapidité d'un programme VB de manière considérable car le programme occuperait beaucoup moins de mémoire en RAM et n'aurait pas à allouer de la mémoire à chaque fois.
Vous n’avez pas trouvé la réponse que vous recherchez ?
crenaud76
Messages postés4172Date d'inscriptionmercredi 30 juillet 2003StatutMembreDernière intervention 9 juin 200628 19 févr. 2004 à 11:28
Sauf que pour cela, tu vas faire une tripoter d'appels API, qui sont super pénalisant !!!!!!!!!
Faut bien doser, car la, je suis aps certain que tu y gagnes bcp !!
ShareVB
Messages postés2676Date d'inscriptionvendredi 28 juin 2002StatutMembreDernière intervention13 janvier 201626 24 févr. 2004 à 09:36
salut
déjà si tu veux de l'optimisation VB super optimisée (lol) je te conseille le livre de M.Curland "Advanced Visual Basic 6"...
(il explique comment booster VB et faire des économies de mémoire, appel de pointeur de fonctions...)
ensuite dans ton cas prend l'api :
SysallocString 'si c'est un pointeur UNICODE
SysAllocStringByteLen 'si c'est un pointeur Ascii
pour eviter les bug quand tu en as plus besoin :
varstr = vbnullstring
jockos
Messages postés321Date d'inscriptiondimanche 22 octobre 2000StatutMembreDernière intervention14 mai 20052 24 févr. 2004 à 10:05
Salut,
J'ai déjà utilisé ces fontions (avec SysFreeString pour libérer la mémoire) en C++ dans des controles ActiveX (sur des BSTR, qui sont des chaines de caractères Unicode correspondant aux String de VB).
Cependant, je ne trouve pas leur profil, ni dans quel fichier elles se trouvent ...
Es-tu sûr que ce sont des API que l'on peut utiliser sous VB et si oui, dans quel fichier (dll) se trouvent-elle ?
jockos
Messages postés321Date d'inscriptiondimanche 22 octobre 2000StatutMembreDernière intervention14 mai 20052 24 févr. 2004 à 10:22
Je suis d'accord avec toi, quand je disais SysFreeString, c'était pour libérer une zone mémoire allouée par SysAllocString ou SysAllocStringLen.
Merci pour ton aide, je vais exploiter la piste que tu m'as donné et essayé de voir ce que cela donne...
Cependant, je ne suis pas sûr que cela va m'avancer beaucoup dans mon problème, car je ne vois pas commet faire pointer 2 variable String sur la même zone mémoire, peut importer si cette zone est alloué avec SysAllocString ou autre chose...
:(
Dim str1 as String
Dim str2 as String
'Allocation d'une String
str1 = SysAllocString("test d'allocation")
'Comment faire pointer str2 sur la éone mémoire de str1 ?
'??????????
ShareVB
Messages postés2676Date d'inscriptionvendredi 28 juin 2002StatutMembreDernière intervention13 janvier 201626 24 févr. 2004 à 10:36
salut
oui effectivement j'avais pas bien compris le prb :
c'est beaucoup plus simple :
tu as un pointeur Ptr vers une zone mémoire contenant tes 500 octets.
tu as str1 et str2 = vbnullstring
tes 2 chaines pointent maintenant vers la zone mémoire.
par contre attention à une chose : si la zone vient à etre libérée avant str1 et str2 il y a risque de plantage
pour libéré str1 et str2
zeromemory byval varptr(str1),4&
zeromemory byval varptr(str2),4&
jockos
Messages postés321Date d'inscriptiondimanche 22 octobre 2000StatutMembreDernière intervention14 mai 20052 24 févr. 2004 à 10:49
Merci beaucoup...
je n'aurais pas pensée à faire "byval varptr(str1)" dans le CopyMemory pour mettre à jour l'adresse de la zone mémoire de str1.
Je vais tester et te tenir au courant.
Pour les problèmes de référence multiple que tu soulèves très justement, je vais faire un compteur de référence sur la zone mémoire pointé pour que la zone mémoire soit libérer si et seulement si il n'y a plus de référence dessus.
Je crois que je vais écrire une sorte de classe VB ou un module VB pour gérer tout cela...
jockos
Messages postés321Date d'inscriptiondimanche 22 octobre 2000StatutMembreDernière intervention14 mai 20052 24 févr. 2004 à 11:22
Test ce bout de code dans un module....
ça marche très bien...
Par contre, ZeroMemory ne marche pas.
Il faut bien comprendre une chose importante.
Quand on déclare une variable str de type String.
Cette variable str est en fait un alias qui représente une adresse mémoire qui contient 4 octets.
Ces 4 octets contiennent eux même l'adresse du buffer recevant la chaine de caractère.
On a donc :
- l'@ de la zone mémoire de 4 octets (pointeur)
- l'@ du buffer contenu dans l'adresse mémoire de 4 octets
C'est pour cela que quand j'affiche les adresses de mes 3 variables dans mon code (str1, str2 et str3), j'ai 3 adresses différentes alors que pourtant, ces 3 variables pointent vein sur la même zone mémoire (contenant la chaine de caractère).
C'est tout à fait normal, car les 3 variables ont un emplacement différent en mémoire, mais elles contiennent toute la même adresse dans leur zone de 4 octets (adresse de la chaine de caractère).
Le copyMemory ByVal VarPtr(str2) ...... affecte bien la zone de 4 octets de str2.
Par contre, à l'affichage (Debug.Print VarPtr(str2), il semblerait que ça affiche l'adresse mémoire de la zone de 4 octets (l'adresse de la cariable str2). Car la valeur est différente pour les 3 variables alors qu'elles pointent toutes sur la même chaine de caractère (zone mémoire partagé).
Pour la désallocation, dans ma fonction de Test, pas de prob lème, Vb se charge de libérer le buffer pointé par str1 puis libère ensuite la zone de 4 octets de str1, str2 et str3.
-----------------------------------------------------------
Private Declare Sub CopyMemory Lib "Kernel32" Alias "RtlMoveMemory" _
(Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Sub ZeroMemory Lib "Kernel32" Alias "RtlMoveMemory" (dest As Any, ByVal numBytes As Long)
Public Sub TestPointer()
Dim str1 As String
Dim str2 As String
Dim str3 As String
End Sub
----------------------------------------------------------
Qu'en penses-tu ?
Vois-tu des problèmes ou des risques (car je sais que quand on manipule les pointeurs, il y a grand danger de laisser des trous de mémoire) surtout avec VB, car on les manipule difficilement d'une façon peu banale et détourné).
En tous cas, merci beaucoup pour ton aide...
Sans toi, je n'aurais pas eu le déclic...
ShareVB
Messages postés2676Date d'inscriptionvendredi 28 juin 2002StatutMembreDernière intervention13 janvier 201626 24 févr. 2004 à 11:55
salut
oui je vois un prb :
à la fin de la fonction il est nécessaire de mettre str2 vbnullstring et str3 vbnullstring. En effet, d'après ce que j'ai pu lire dans le livre cité plus haut : il faut impérativement supprimer les référence à une zone mémoire partagée avant que VB ne tente de libérer cette zone car il tenterait alors de libérer 3 fois la zone dans notre cas == plantage
Varptr renvoit l'addresse de du pointeur alors que Strptr renvoit l'adresse contenue dans le pointeur.
jockos
Messages postés321Date d'inscriptiondimanche 22 octobre 2000StatutMembreDernière intervention14 mai 20052 24 févr. 2004 à 16:07
Le vbNullString fait 2 choses :
- il libère le buffer contenant la chaine de caractère
- il met 0 dans l'adresse du buffer (zone de 4 octets)
Quand à la zone mémoire de 4 octets contenant l'adresse de la chaine de caractère, elle est libéré quand la durée de vie de la variable VB se termine (portée de la variable).
Il faut faire attention au fait que dès qu'une variable String va être détruite par VB (fin de sa portée --> durée de vie), la zone mémoire pointé contenant la chaine de caractère va être détruite et si d'autre variable String pointe dessus, elle ne pointeront sur rien et on aura à coup sur une erreur fatal de type "La mémoire ne peut pas être "written" ou "read" sous 2000/XP).
Bref, je voudrais trouver le moyen de faire le VbNullString manuellement, mais sans désallouer la chaine de caractère (sauf si plus aucune variable ne pointe dessus).
Je voudrais donc juste mettre la zone de 4 octets (pointeur) d'une variable String à 0, mais le ZeroMemory ne marche pas en faisant ByVal VarPtr(str1)..... Windows m'engueule en me disant que j'accède à une zone mémoire sans autorisation (la mémoire ne peut être "written")...
Comment faire... pour que quand la variable sera détruite par VB, la zone mémoire pointé ne soit pas libérer ?
Je n'ai pas trop de solution... il faut comme tu me l'avais dit que je mette 0 (équivalent de NULL pour les pointeurs en C/C++) dans la zone de 4 octets de la variable.
Mais ZeromMemory ne marche pas ....
ShareVB
Messages postés2676Date d'inscriptionvendredi 28 juin 2002StatutMembreDernière intervention13 janvier 201626 24 févr. 2004 à 17:17
salut
attention à la déclaration, la bonne est :
Private Declare Sub ZeroMemory Lib "Kernel32" Alias "RtlZeroMemory" (dest As Any, ByVal numBytes As Long)
(tu avais mis RtlMoveMemory)
maintenant comme ca marche
zeromemory byval varptr(str2),4&
ShareVB
Messages postés2676Date d'inscriptionvendredi 28 juin 2002StatutMembreDernière intervention13 janvier 201626 24 févr. 2004 à 17:17
salut
attention à la déclaration, la bonne est :
Private Declare Sub ZeroMemory Lib "Kernel32" Alias "RtlZeroMemory" (dest As Any, ByVal numBytes As Long)
(tu avais mis RtlMoveMemory)
maintenant comme ca marche
zeromemory byval varptr(str2),4&