Error CopyMemory y estructura SafeArray (Via API)

Iniciado por BlackZeroX, 24 Agosto 2010, 02:27 AM

0 Miembros y 2 Visitantes están viendo este tema.

BlackZeroX


Edito:

Antes que nada No es factible hacer un Simple Copymemory por que Crashea!¡ de forma instantanea asi que para esto hay que manipular y bloquear el Array con la estructura SafeArray.

Pero aun no encuentro la Solución
[/i][/b]

intento copiar el contenido de una variable tipo variant a una avriable de matrix variant

Código (vb) [Seleccionar]


Dim VarVariant as variant



a

Código (vb) [Seleccionar]


Dim VarVariantDest() as variant



La cosa es sencilla, copia bien la primera vez posteiormente me crashea... y creo que es por la Estructura SafeArray, ( ya intente varias cosas incluida sin Apis y con solo manejo de la dicha Estructura y sigue de la misma manera!¡. )

Aqui el codigo

Código (vb) [Seleccionar]


Option Explicit
Option Base 0

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
       (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function SafeArrayAccessData Lib "Oleaut32" _
       (ByVal psa As Long, pvData As Long) As Long
Private Declare Function SafeArrayUnaccessData Lib "Oleaut32" _
       (ByVal psa As Long) As Long
'   //  msvbvm60.DLL
Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" _
   (Var() As Any) As Long

Private Sub Test_Translate()
   Dim VarVariant          As Variant
   Dim VarVariantDest()    As Variant
   Dim aaa(0 To 3)         As Variant
   Dim psa                 As Long
   Dim pData               As Long
   
   aaa(0) = "Miguel"
   aaa(1) = "Angel"
   aaa(2) = "Ortega"
   aaa(3) = "Avila"
   
   VarVariant = aaa
   
   ReDim Preserve VarVariantDest(0 To 7)
   CopyMemory psa, ByVal VarPtr(VarVariant)+8, 4
   
   If SafeArrayAccessData(psa, pData) = 0 Then   ' Bloqueo el Array y obtengo el puntero de varptr(VarVariant(0))
       CopyMemory VarVariantDest(4), ByVal pData, 4 * 16  ' Copio el Contenido
       SafeArrayUnaccessData psa  ' Desbloqueo el array
   End If
   
   For psa = LBound(VarVariantDest) To UBound(VarVariantDest)
       Debug.Print psa, VarVariantDest(psa)
   Next psa
End Sub

Private Sub Form_Load()
Dim i       As Byte
   For i = 1 To 10
       Call Test_Translate
       MsgBox "Prueba: " & i
   Next i
End Sub



Dulces Infierno Lunar!¡.
The Dark Shadow is my passion.

BlackZeroX

#1
solo como dato para no matarse , la estructura SafeArray es de 16 Bytes aqui se las dejo por si alguien la requiere con esta cuestion!¡.

Código (vb) [Seleccionar]


Private Type SafeArrayReader
   cDims As Integer            ' nr of dimensions for the array
   fFeatures As Integer        ' extra information about the array contents
   cbElements As Long          ' nr of bytes per array element. Possible Examples: 1=byte,2=integer,4=long,8=currency
   cLocks As Long              ' nr of times array was locked w/o being unlocked
   pvData As Long              ' address to 1st array item, can be a pointer to another structure/address
End Type



Nota: Solo Array's, aun queen este caso...

Dulces Lunas!¡.
The Dark Shadow is my passion.

Tokes

Oye, BlackZeroX, no entiendo algo (por no decir todo):

¿La variable psa que papel juega ahí?

¿Si la usamos en copymemory que es lo que hace?

Si ejecuto tu código como está se cierra visual basic.

Si lo ejecuto así, ya no se cierra:

If SafeArrayAccessData(VarPtr(VarVariant), pData) = 0 Then

aunque, claro, no tengo ni la menor idea de que es lo que hace.

               Saludos.

BlackZeroX

#3
PSA es el puntero a la estructura SafeArray

es decir hay algo que no saben muchos y es que una variable es una estructura... pero en este caso PSA son los 4 primeros bytes a esta (SAFEARRAY) la cual contiene informacion de la variable, si es una variable Variant sin matrix los 4 primeros bytes indican el tipo del mismo los siguientes estas vacios y los 4 siguientes indican el puntero al contenido (en este caso seria asi, si fuese un array la estructura que puse arribita es la usada para saber TODA la informacion de una variable tipo Array, Dimenciones, cuanto pesa una dimencion y por ende la lontitud en bytes del array, el incice inferior, el tipo Gral del Array)!¡.

aqui hay un link a la MSDN

http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.ole.interop.safearray.aspx

Edito:-------------------------->

Código (Vb) [Seleccionar]


If SafeArrayAccessData(VarPtr(VarVariant), pData) = 0 Then



Esta mal debes pasarle el puntero del SafeArray mas no el de la Variable, SafeArrayAccessData = 0 cuando sale todo bien cualquier otro valor es un Error.

Dulces Lunas!¡.
The Dark Shadow is my passion.

LeandroA

hola BlackZerox lo que pusiteen este link me funciona bien no entiendo cual es el problema.

Saludos.

BlackZeroX

#5
Ok bien el problema es el siguiente

en aquel es de esta forma

VarVariantOri() -> VarVariantDest()

el problema aqui y ahora es

VarVariantOri() -> VarVariantAux - VarVariantDest()

Los codigos aunque se parecen, realmente SON DISTINTOS!¡.

Si pruebas el codigo de arriba veras que te va a Crashear, el otro no te crasheara por que ya esta bien!¡.

Dulces Lunas!¡.
The Dark Shadow is my passion.

Karcrack

#6
Antes de ponerme a codear nada... Tu lo que quieres hacer es establecer un nuevo Array tipo Variant en el que el primer valor sea aaa?

MOD:
http://www.vbforums.com/showthread.php?t=625615
:o :o :o Psyke tiene un primo Ingles!!! :laugh:

Psyke1

Cita de: Karcrack en 24 Agosto 2010, 11:20 AM
Antes de ponerme a codear nada... Tu lo que quieres hacer es establecer un nuevo Array tipo Variant en el que el primer valor sea aaa?

MOD:
http://www.vbforums.com/showthread.php?t=625615
:o :o :o Psyke tiene un primo Ingles!!! :laugh:
Jajajajajajaj  :laugh: :laugh:
Pregunte en vbforums para ver si podian resolverlo, que a mi tambien me interesa... ;)

DoEvents¡! :P

Psyke1

#8
Esta es la respuesta que me han dado traducida con Google ( no os riais :P ):
CitarCrashea porque los artículos VarVariantDest de 4, 5, 6 y 7 contienen los punteros a los datos exactamente la misma cadena que está contenido por la AAA.

Al final del procedimiento Test_Translate, cuando se limpia las cosas, dicen que primero destruye aaa y todas las cadenas contenidas en él. A continuación se limpia VarVariantDest - pero contiene punteros a las cadenas que ya han sido destruidos. Resultado final: usted obtiene un accidente.

En este caso es mucho mejor usar la antigua forma para copiar el contenido de la matriz, especialmente si usted no está tratando de lograr la eliminación de los elementos de la matriz original y simplemente colocando el directamente en la matriz de otros.

Citar¿No sabe cómo está familiarizado con el almacenamiento de cadenas / referencias. Una cadena almacenada dentro de nada: matriz variante, o, simplemente, una variable de cadena en realidad no contienen los datos de cadena. Los datos de cadena se almacena en otra parte de la memoria.

variable de cadena: la variable contiene una cadena de bytes puntero del 4 al carácter primero de los datos de la cadena
matriz de cadenas dinámica: la matriz se compone de 4 entradas de bytes. Cada entrada de la matriz es un puntero de cadena
variante: los datos dentro de la variante es un puntero de cadena

Cada vez que un puntero de cadena se copia con CopyMemory, va a copiar el puntero, no la cadena. Cuando una cadena se copia con VB (es decir, newString oldString =), una nueva cadena se crea y cada variable tiene un puntero distinto. Si un puntero se duplica con cada vez CopyMemory, una copia de ese puntero debe ser llevado a cero otra cosa que obtener accidentes. Como Merri explicó esto se debe a VB limpia las cuerdas y que está tratando de limpiar la misma cadena dos veces. La primera vez que está bien, la memoria por segunda vez ya no se asigna y se bloquea la aplicación.
Mira esto: http://www.codeguru.com/vb/gen/vb_misc/algorithms/article.php/c7495

Fuente:
http://www.vbforums.com/showthread.php?p=3870342#post3870342

DoEvents¡!
:P

BlackZeroX

#9
.
mmm como dato es cuando se consultan los valores de VarVariantDest despues de haber hecho el CopyMemory (en el For Next), bueno mejor dicho el Crash no se presenta al final del proceso se Produce en la Consulta

La solucion que estoy viendo es obtener el puntero a la matriz aaa() por medio de VarVariant, haber si lo calculo, ya les cuento!¡.


Dulces Lunas!¡.
The Dark Shadow is my passion.