Newsgroup: it.comp.lang.visual-basic
Titolo: [?] Come trovo la dimensione di una variabile in memoria

Devo inviare attraverso Winsock una variabile strutturata +o- come
l'esemio (nel mio prog č molto piů complessa) e l'unico modo č
convertirla in un array di byte, ho trovato l'API CopyMemory che in
altre occasioni funge egregiamente, il problema sorge quando devo
passargli la dimensione della variabile, e sia Len che LenB non sono
in grado di darmi la dimensione in Byte di una variabile "user-defined"
con all'interno dei Dynamic Array.
Esempio "semplificato e non funzionante"
==============================================================================
Declare Sub CopyMemory Lib "Kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, _
                       ByRef Source As Any, ByVal numbytes As Long)
Public Type TypTipo01
   MyVar01 As Date
   MyVar02 As Byte
   MyVar03 As Long
End Type
Public Type TypTipo02
   MyVar01 As Long
   MyVar02 As Long
   MyArray() As TypTipo01
End Type
Public Sub Send(prmDati As TypTipo02)
'il problema sorge quando devo dimensionare TmpArray
'e quando chiamo CopyMemory
Dim TmpArray(LenB(prmDati)) As Byte
  CopyMemory TmpArray(0), prmDati, LenB(prmDati)
  WinSock.SendData TmpArray
End Sub
==============================================================================
-----
CIAnO

 escribió en el mensaje de noticias
txUj8.64669$Ns4.2...@news2.tin.it...
Se sbaglio che qualcuno me lo confermi
prmDati no prende il totale di TypTipo02
ma e quasi come creare una colecione quindi devi dire cosa ci metti dentro
prmDati.MyVar01=
prmDati.MyVar02=
prmDati.MyArray(n).MyVar01[del type TypTipo01]=
prmDati.MyArray(n).MyVar02[del type TypTipo01]=
prmDati.MyArray(n).MyVar03[del type TypTipo01]=
fatto questo
ti leggi e ti sommi tutti i valori LenB
e con il risultato  prepari lo spazio che hai bisogno per prmDati
ciao L'oriundo

 wrote in message
news:txUj8.64669$Ns4.2...@news2.tin.it...
Se l'array è dinamico la lunghezza la devi calcolare in run time in base
alla dimensione
effettiva del momento (che può cambiare da una volta all'altra).
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 con all'interno dei Dynamic Array.
Certo, perchè gli array dinamici e le stringhe dinamiche(che alla fine sono
array dinamici di byte) vengono referenziati con il loro puntatore.
Quindi per ogni membro dinamico VB calcola giustamente 4 byte e non la
lunghezza del dato che sta da tutt'altra parte e non nella struttura.
Secondo me per il tipo di applicazione che stai facendo il tuo approccio è
sbagliato.
Dovrebbe essere qualcosa tipo:
Public Type TypTipo02
   MyVar01 As Long
   MyVar02 As Long
   DataLen As Long
End Type
Dim Header As TypTipo02
Dim Data() As TypTipo01
E mandare separatamente le due info, così le puoi misurare.
Ciao

 con all'interno dei Dynamic Array.
negli array dinamici la memoria non è contigua di conseguenza non puoi
copiarla con una sola istruzione
ciao

 copiarla con una sola istruzione
Invecie sě :P
Ciao


invece no ehhehehe :)))
Se non ho cpaito male parlava di type con all'interno array dinamici .
Puntatori dinamici all'interno di una type vengono allocati a runtime e di
conseguenza la memoria non è contigua a quella allocata in avvio del
programma, di conseguenza non puoi copiare una type con l'intero contenuto.
ciao :))

 Se non ho cpaito male parlava di type con all'interno array dinamici .
Ma tu parlavi di array, non di type!
E i dati negli array sono contigui.
Ciao

con all'interno dei Dynamic Array.
cmq spero che ci siamo capiti ......forse :))))))
ciao :)

 cmq spero che ci siamo capiti
Sě, ci siamo capiti :) č solo una questione di logica nella sequenza
domanda->risposta.
Purtroppo noi programmatori non possiamo dare per scontato niente.
Ciao

 ha scritto nel messaggio news:u8%j8.14606$%g7.4...@twister2.libero.it...

Hai compreso benissimo il problema.
Dunque devo rassegnarmi a non poter usare direttamente la struttura dati
che ho già, e che funziona che è una meraviglia, come versatilità poi!!!
PS. Il problema e che non mi posso permettere di sconvolgere la struttura,
che è mooolto più complessa dell'esempio, molti più array e type nidificati.
-----
CIAnO


Grazie per le risposte.
Ho visto che molto probabilmente non si può fare direttamente con quel
tipo di struttura dati e allora completo la panoramica del problema.
Ho un programma che ottimizza dei parametri di una funzione (creata da me)
calcolando i risultati con tutte le varie combinazioni, e siccome dando un
range di test abbastanza ampio vengono fuori centinaia di milioni di
iterazioni, volevo dividere il carico su più PC in rete "distributed
computing"(1), la struttura nuova del prog me lo permette già, basterebbe
eseguire il prog modificato con l'interfaccia di rete su i client.
Devo trovare un modo semplice di inviare i risultati tramite tcp/ip, perchè
la struttura dati dei risultati non è "semplice" come nell'esempio, e non
vorrei dover rinunciare ad una parte dei dati (il dettaglio) che per il
momento non uso ma non si sa mai.
Sotto la firma c'è la struttura completa da trasferire, manca la struttura
per i dati su cui si appoggia la funzione, ma per quella posso far caricare
i dati direttamente dal DB e calcolare il resto.
PS. a livello di prestazioni di calcolo non c'è confronto con il software
    in commercio, poi rendendolo capace di lavorare su più processori !!!
--------------------------------------------------------------------------
(1)Termine sempre molto valido.
 CIAnO
--------------------------------------------------------------------------
  Struttura Type per i risultati, parametri funzione, parametri test
--------------------------------------------------------------------------
'======================================================================
' Risultati
Public Type TypRisultatiInteger
   OperazioniTot As Integer
   Vinte As Integer
   Perse As Integer
   Guadagno As Long
   Perdite As Long
   Totale As Long
End Type
Public Type TypOperazioni
   IndexOpen As Long
   IndexClose As Long
   Acquisto As Long
   Vendita As Long
   Profit As Long
   Stop As Long
   TrailingLevel As Long
   TrailingStop As Long
End Type
Public Type TypSubOperazioniTest
   Data As Date
   OperazioniTot As Byte
   Vinte As Byte
   Perse As Byte
   Guadagno As Long
   Perdite As Long
   Totale As Long
   Operazioni() As TypOperazioni
End Type
Public Type TypOperazioniTest
   Risultati As TypRisultatiInteger
   Parametri As TypParametriSistema
   OpGiornaliere() As TypSubOperazioniTest 'Array con il dettaglio
End Type
'======================================================================
' Parametri per la funzione
Public Type TypStrategieAttive
   Medie As Boolean
   MACD As Boolean
   RSI As Boolean
   Profit As Boolean
   Stop As Boolean
   OpenBreak As Boolean
   CloseBreak As Boolean
   CloseProfit As Boolean
   CloseStop As Boolean
   CloseTrailing As Boolean
End Type
Public Type TypParametriSistema
   MinutiMedia1 As Byte
   MinutiMedia2 As Byte
   MinutiMACDFast As Byte
   MinutiMACDSlow As Byte
   MinutiMACDMedia As Byte
   TolleranzaMedie As Byte
   TolleranzaMACD As Byte
   StrategieAttive As TypStrategieAttive
   Profit As Long
   Stop As Long
   TrailingStop As Long
   Limite1 As Long
   Limite2 As Long
   Limite3 As Long
   Stop1 As Long
   Stop2 As Long
   Stop3 As Long
End Type
'======================================================================
' Parametri per il test
Public Type TypValoriTest
   Min As Integer
   Max As Integer
   Step As Byte
End Type
Public Type TypParametriTest
   MinutiMedia1 As TypValoriTest
   MinutiMedia2 As TypValoriTest
   MinutiMACDFast As TypValoriTest
   MinutiMACDSlow As TypValoriTest
   MinutiMACDMedia As TypValoriTest
   TolleranzaMedie As TypValoriTest
   TolleranzaMACD As TypValoriTest
   StrategieAttive As TypStrategieAttive
   Profit As TypValoriTest
   Stop As TypValoriTest
   TrailingStop As TypValoriTest
   Limite1 As TypValoriTest
   Limite2 As TypValoriTest
   Limite3 As TypValoriTest
   Stop1 As TypValoriTest
   Stop2 As TypValoriTest
   Stop3 As TypValoriTest
   DataInizio As Date
   DataFine As Date
End Type

 che ho già, e che funziona che è una meraviglia, come versatilità poi!!!
rassegnarsi mai la puoi copiare in più passaggi ovviamente se sai come
ricavare la grandezza dei vari array.Copymemory è il metodo giusto
ciao :)

 "user-defined" con all'interno dei Dynamic Array.
E' il classico problema della serializzazione (conversione di una 
struttura non contigua in un array di byte). Se non fossi costretto ad 
usare una socket, potresti usare DCOM, se ne occuperebbe OLE tramite il 
suo meccanismo di marshalling. Comunque, ti posso dire come fa Windows 
NT per far ereditare ai processi creati con CreateProcess dati dinamici 
come le stringhe (directory attuale, environment, eccetera)
In tutti i processi esiste un oggetto (una struttura, come un Type di 
Visual Basic) chiamato Process Environment Block (PEB) - che ora non 
considereremo - che a sua volta ha un puntatore ad un oggetto chiamato 
Process Parameters Block (PPB). Il PPB contiene un sacco di parametri 
stringa, che si trovano dunque ad indirizzi di memoria imprevedibili
Il problema è: trasferire tutta questa roba con una sola operazione di 
copia. Perchè le operazioni di copia di memoria tra processi sono 
piuttosto noiose, e piene di limitazioni. Per ottenere ciò, le stringhe 
vengono copiate in coda alla struttura, una dopo l'altra, e i puntatori 
alle stringhe vengono "normalizzati", ossia convertiti da puntatori a 
memoria virtuale in distanze in byte dall'inizio della struttura. Sei 
già scappato? dai, resisti ancora un po'. Il PPB, supersemplificato, è 
così:
Type UNICODE_STRING
 Length As Integer 'lunghezza in byte della stringa puntata da Buffer
 MaximumLength As Integer 'lunghezza massima in byte di Buffer
 Buffer As Long 'puntatore ad Integer
End Type
Type RTL_USER_PROCESS_PARAMETERS
 MaximumLength As Long
 Length As Long
'omissis
 DllPath As UNICODE_STRING
 ImagePathName As UNICODE_STRING
 CommandLine As UNICODE_STRING
'omissis
 WindowTitle As UNICODE_STRING
'omissis
End Type
La normalizzazione lo trasforma così (ogni riga dello schema ha le 
dimensioni di un Long):
+-------------------------------------------------+
| MaximumLength = X * 4KB [1]                     | &H00 [3]
| Length        = Y       [2]                     | &H04
  ...                                               ...
| DllPath: [4]   Length = 34, MaximumLength = 36  | &H30
|                Buffer = &H94                    |
| ImagePathName: Length = 32, MaximumLength = 32  | &H34
|                Buffer = &HB8                    |
| CommandLine:   Length, MaximumLength            | &H34
|                Buffer                           |
  ...                                               ...
| WindowTitle:   Length, MaximumLength            | &H70
|                Buffer                           |
  ...                                               ...
| "C:" 'DllPath.Buffer - ogni carattere ha le     | &H94
| "\w" 'dimensioni di un Integer                  |
| "in"                                            |
| "do"                                            |
| "ws"                                            |
| "\s"                                            |
| "ys"                                            |
| "te"                                            |
| "m" + Chr(0)                                    |
| "C:" 'ImagePathName.Buffer                      | &HB8
| "\w"                                            |
| "in"                                            |
| "nt"                                            |
| "\f"                                            |
| "oo"                                            |
| ".e"                                            |
| "xe"                                            |
  'seguono gli altri buffer
  ...
| 'byte inutilizzati di padding per raggiungere   |
| 'le dimensioni di un multiplo di 4kb            |
+-------------------------------------------------+
[1] MaximumLength è sempre un multiplo di 4KB, perchè la struttura deve 
venire allocata con VirtualAlloc, che può allocare solo a blocchi di 
una pagina di memoria (e ogni pagina ha le dimensioni di 4KB, almeno 
sugli Intel x86 a 32 bit)
[2] Y sono i byte realmente usati, cioè MaximumLength meno i byte di 
padding. Questo serve a copiare solo i byte che servono realmente
[3] in questa colonna ci sono i byte di distanza (offset) del campo 
rispetto all'inizio della struttura
[4] notare come:
 - il campo Length sia la lunghezza reale della stringa
 - il campo MaximumLength sia la lunghezza della stringa arrotondata ad
   un multiplo di 4 (dimensioni in byte di un Long)
 - il campo Buffer non sia un vero puntatore, ma un intero: l'offset
   del buffer rispetto alla struttura
Ora, questo coso viene copiato dal processo A al processo B (previa 
allocazione tramite VirtualAllocEx di MaximumLength byte nel processo 
B). Si riesce a copiarlo in un solo viaggio, perchè è un blocco unico, 
grazie alla normalizzazione. Il campo ProcessParameters del PEB di B 
viene fatto puntare al PPB. Il processo B viene svegliato, e le sue 
routine di inizializzazione denormalizzano il PPB, cioè ritrasformano 
gli offset in puntatori
Mettiamo che il PPB sia stato caricato all'indirizzo &H7AB17000. 
DllPath.Buffer ad esempio viene denormalizzato in questo modo:
Let PPB.DllPath.Buffer = &H7AB17000 + PPB.DllPath.Buffer
o meglio:
Let PPB.DllPath.Buffer = VarPtr(PPB) + PPB.DllPath.Buffer
A questo punto sei autorizzato a raggiungere il più vicino oggetto 
contundente e sfracassarmelo sul cranio
Non son sicura che questa perversione sia realizzabile in VB. Anzi, 
tutt'altro. Comunque, se ti interessa e se riesci a tradurre tutto ciò 
in VB, funziona
Il problema è che VB per gli array dinamici usa una struttura 
orribilmente complicata. Io avevo iniziato una classe per gestire 
vettori arbitrari, e ne stavo progettando una per gestire interamente 
in memoria strutture con qualsiasi tipo e numero di record, ma non ho 
mai trovato motivazioni per continuare (son passata al Delphi e al C, e 
improvvisamente due progetti del genere hanno perso senso)
Se ti interessa, li continuo
-- 
 < 
http://www.reactos.com/
 >  Open source clone of Windows NT. Current
     Don't stand, REACT!      version 0.0.19. C, C++ and ASM developers
                              and beta testers are welcome!


Grazie a Juliet per l'illuminante "articolo"[1] e grazie a Tino per
avermi ridato la speranza. ;-)
Certi concetti (serializzazione) a volte sono cosi' scontati che uno non
ci pensa finche non li vede scritti.
Faro' qualche prova e vi faro' sapere.
PS.Casomai mi ingarbugliassi da qualche parte, vi trovo sempre qui vero! :)
CIAnO
[1]non si poteva chiamare semplicemente post.