![]() |
|
|
|
#1
|
|||||
|
|||||
|
Quote:
Hmm. OK, that's too bad...But anyway, the Byte Comb link you provided helps a little on that. Quote:
Well, its only a theory and I think it crashes before the lineCode:
Set ObjectFromPointer = oTemp I also learned since that the first two options below will crash excel... Code:
Sub crashMem_Copy()
Dim lptr As LongPtr
' Mem_Copy lptr, ByVal 0, 4 'crashes excel
' Mem_Copy lptr, ByVal lptr, 4 'crashes excel
Mem_Copy lptr, lptr, 4 'is fine
End Sub
Quote:
![]() Quote:
Code:
Sub getReference()
#If Win64 Then
Const PTR_LENGTH As Long = 8
#Else
Const PTR_LENGTH As Long = 4
#End If
Const coBytes As Long = 4
Dim objwks As Worksheet, lptr As LongPtr, objName As String, objwksPtr As LongPtr
Debug.Print
' Sheet1 Object reference and first coBytes bytes
lptr = objPtr(Sheets(1)): objName = "Sheet1 "
Debug.Print PointerToSomething(objName, lptr, coBytes) & vbTab & "using objPtr"
' Using objPtr, can't diferentiate because the reference is resolved before reporting
Set objwks = Sheets(1)
lptr = objPtr(objwks): objName = "objwks "
Debug.Print PointerToSomething(objName, lptr, coBytes) & vbTab & "using objPtr"
' Using varPtr, can diferentiate.
' The local Worksheet Object is treated as a reference, not an Object: the reference is not resolved
lptr = VarPtr(objwks): objName = "objwks "
Debug.Print PointerToSomething(objName, lptr, coBytes) & vbTab & "using varPtr"
' The contents of the local variable (objwks) is the address of the global object but byte-reversed (little endian)
' Load the reference into a LongPtr type and read back the byte-corrected (big endian) value of the reference
Mem_Copy objwksPtr, ByVal VarPtr(objwks), PTR_LENGTH
Debug.Print objName & vbTab & "points to: " & "0x" & HexPtr(objwksPtr)
' Can also do this passing objwks as ByRef (default)
Mem_Copy objwksPtr, objwks, PTR_LENGTH
Debug.Print objName & vbTab & "points to: " & "0x" & HexPtr(objwksPtr)
' Or like this...
Mem_Copy ByVal VarPtr(objwksPtr), objwks, PTR_LENGTH
Debug.Print objName & vbTab & "points to: " & "0x" & HexPtr(objwksPtr)
End Sub
Code:
Sheet1 : Address: 0x18240578 : Contents: 0xC0EA4C18 using objPtr objwks : Address: 0x18240578 : Contents: 0xC0EA4C18 using objPtr objwks : Address: 0x002AEF90 : Contents: 0x78052418 using varPtr objwks points to: 0x18240578 objwks points to: 0x18240578 objwks points to: 0x18240578 And here you can see how the local variable's value is zero when its set to nothing... Code:
Sub getReference2()
#If Win64 Then
Const PTR_LENGTH As Long = 8
#Else
Const PTR_LENGTH As Long = 4
#End If
Const coBytes As Long = 4
Dim objwks As Worksheet, lptr As LongPtr, objName As String, objwksPtr As LongPtr
Debug.Print
' Sheet1 Object reference and first coBytes bytes
lptr = objPtr(Sheets(1)): objName = "Sheet1 "
Debug.Print PointerToSomething(objName, lptr, coBytes) & vbTab & "using objPtr"
' Using varPtr, can see the local variable is set to nothing.
' The local Worksheet Object is treated as a reference, not an Object: the reference is not resolved
lptr = VarPtr(objwks): objName = "objwks "
Debug.Print PointerToSomething(objName, lptr, coBytes) & vbTab & "using varPtr, set to Nothing"
' Using objPtr, can't diferentiate because the reference is resolved before reporting
Set objwks = Sheets(1)
lptr = objPtr(objwks): objName = "objwks "
Debug.Print PointerToSomething(objName, lptr, coBytes) & vbTab & "using objPtr"
' Using varPtr, can diferentiate.
' The local Worksheet Object is treated as a reference, not an Object: the reference is not resolved
lptr = VarPtr(objwks): objName = "objwks "
Debug.Print PointerToSomething(objName, lptr, coBytes) & vbTab & "using varPtr"
' The contents of the local variable (objwks) is the address of the global object but byte-reversed (little endian)
' Load the reference into a LongPtr type and read back the byte-corrected (big endian) value of the reference
Mem_Copy objwksPtr, ByVal VarPtr(objwks), PTR_LENGTH
Debug.Print objName & vbTab & "points to: " & "0x" & HexPtr(objwksPtr)
End Sub
Code:
Sheet1 : Address: 0x18240578 : Contents: 0xC0EA4C18 using objPtr objwks : Address: 0x002AEF90 : Contents: 0x00000000 using varPtr, set to Nothing objwks : Address: 0x18240578 : Contents: 0xC0EA4C18 using objPtr objwks : Address: 0x002AEF90 : Contents: 0x78052418 using varPtr objwks points to: 0x18240578 Quote:
In summary, I cant see any reason to set local objects to nothing at the end of a sub. Even if there is an error and the sub doesn't complete normally, or if there are structures that fool the reference counting, everything is still cleaned up in the former and the set to nothing does nothing extra in the latter. I learned a lot from this exercise and added some nice routines to my library, so this has been most interesting! For anyone who wants to run the above routines, here is a .bas file with everything you need... well its .txt but just need to change it to .bas and you can import into a module. Last edited by CoolBlue; 06-22-2014 at 08:38 AM. Reason: added .bas attachment; added outputs from debug window |
|
#2
|
|||
|
|||
|
Sorry for the delay, but i kept thinking and thinking ...
![]() Point1: Post #35 I basically share your opinion about the application crash on the attempt to Mem_copy something what doesn't match a 4 Bytes Code. By accident I choose first a range-object (and experienced the crashes), afterwards I changed to a worksheet-object (avoiding crashes I didn't any mem-copy to an object or a variant). I was just looking at the numbers of ObjPtr which are always the same whether you obtain them directly from the object ObjPtr(Sheet1) or from the variable ObjPtr(objwks) Therefore I wondered, why did excel crash, because even with the variable gone I ask at the end of the Copy of ObjPtr(Range("A1")), and since the Range still exists and hasn't changed, what's the problem to copy it? It took me a long time to figure out there is a difference between Range and Worksheet: Whereas Worksheet keeps his pointer throughout the application, this isn't the case with Range. A Range changes its pointer, furthermore the variable (objRange) set to the Range is assigned another pointer. I said the choice was by accident but actually I'm glad about the choice because otherwise it would have led in a complete different direction... Point2: I regret the lack of knowlegde about the architecture of objects and what they look like in memory. I really do, probably it would make things a lot easier knowing about this things. Point3: Quote:
![]() But Yes, I agree, at least for the moment let's depend on the change. Point4: According to Point 4, I agree, memory is freed whether or not the variable is set to Nothing (at least valid for the macros I tried up to now). A surprise to me: Classes are destroyed without explicity destroying them. But I don't agree on this Quote:
Attached the file including 4 tests - as well the CircRef - with some kind of summary. |
|
#3
|
||||||
|
||||||
|
Quote:
I'm surprised that the crashMem_Copy routine in my previous post crashes excel because the destination pointer is fine. Why crash when the source pointer is set to zero? Its only a read... Any thoughts? Quote:
But your link was very helpful, I've seen the byte comb site before but it was good to be reminded of it, it informed my thinking on this. Quote:
Quote:
Its quite simple really, all object life cycle is managed by reference counting: when the reference count goes to zero, the object is scheduled for deletion. There are no no exceptions. I guess this will be a background process that is run when VBARuntime has free time and it will just scan the reference count field in the object table and "Erase" those with zero reference. The ERASE method will not delete the object from the object table, but it will release any memory used by the object's structure. Quote:
![]() The full quote on this is: Quote:
I am saying that setting to nothing does nothing extra in these cases. Im saying it makes no difference. The problem will still be there. I am arguing against using set to nothing remember? ![]() As you can see in your example, the result after run-time is the same if you have Code:
Set objcls1 = Nothing Code:
'Set objcls1 = Nothing So, the two points I was trying to argue against are:
And thanks for the attachment... your documentation style is much nicer than mine, I will study it and improve my ways!
|
|
#4
|
|||
|
|||
|
Quote:
And I remember very well that you argue against - therefore we are here But I enjoy. That way I learn quite a lot about memory, which really is due in regard that obviously MS has improved on the subject.Yeah, the VarPtr of an object - honestly I don't know if it makes sense. I tried to figure out whether the Mem_ReadHex of VarPtr points to the ObjPtr by converting the HexToDec, but was disapointed by the result. Even worse HexToDec comes up with negative figures, so what shall we make of this? Maybe Val("&H"&...) isn't the right tool? Quote:
Documentation is a selfish thing - I know after several days I will end up with x files not knowing anymore what I intended to achieve, just testing, playing, ... But one thing is sure, the time I used formatting the immediate window, I rather would have spent for another output. But for the moment it's ok.Me as well, I spent a lot of time searching the web for information about "memory" and related words, but google misunderstands what I'm looking for, and mostly comes up with things I'm not interested in. |
|
#5
|
||||
|
||||
|
Quote:
![]() And yes, I agree, its a good idea to set objects to nothing earlier if you don't need them anymore... but if you are already at the end of the sub then... yep, we agree on that. Quote:
![]() Quote:
The memory image is in a format called little endian. Intel-based systems store bytes little end first so the least significant byte is on the left. You have to flip the bytes to see the true hex value... If you look at the last section of getReference2() in my previous post you will see how that I move the contents of the local pointer (the address of Sheet1) into another LongPtr type called objwksPtr. I can then print out the hex value of that pointer and VBA will interpret it correctly. Code:
01 Sheet1 : Address: 0x1D6DA618 : Contents: 0xC0EA4C18 using objPtr
02 objwks : Address: 0x002AEF90 : Contents: 0x00000000 using varPtr, set to Nothing
03 objwks : Address: 0x1D6DA618 : Contents: 0xC0EA4C18 using objPtr
04 objwks : Address: 0x002AEF90 : Contents: 0x18A66D1D using varPtr
05 objwks points to: 0x1D6DA618
Line 04 is from this...
' Using varPtr, can diferentiate.
' The local Worksheet Object is treated as a reference, not an Object: the reference is not resolved
lptr = VarPtr(objwks): objName = "objwks "
Debug.Print PointerToSomething(objName, lptr, coBytes) & vbTab & "using varPtr"
It produces this image of the contents of the objwks reference
0x18A66D1D
Line 05 is from this
' The contents of the local variable (objwks) is the address of the global object but byte-reversed (little endian)
' Load the reference into a LongPtr type and read back the byte-corrected (big endian) value of the reference
Mem_Copy objwksPtr, ByVal VarPtr(objwks), PTR_LENGTH
Debug.Print objName & vbTab & "points to: " & "0x" & HexPtr(objwksPtr)
It produces this image of the contents of the objwks reference
0x1D6DA618
And this is the correct address of the Sheet1 Object
But in fact they are the same number but in different formats...
1D6DA618 18A66D1D
Ive also attached a couple of pics to try to make it clear... |
|
| Thread Tools | |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Wierd "script code" in a downloaded .doc file | CNBarnes | Word | 2 | 10-18-2012 02:07 AM |
replace data from variable with "sub and super script" from excel to word by vba
|
krishnaoptif | Word VBA | 9 | 06-22-2012 05:08 AM |
How to choose a "List" for certain "Heading" from "Modify" tool?
|
Jamal NUMAN | Word | 2 | 07-03-2011 03:11 AM |
| Rules and Alerts: "run a script"? | discountvc | Outlook | 0 | 06-15-2010 07:36 AM |
| An "error has occurred in the script on this page" | decann | Outlook | 8 | 09-03-2009 08:54 AM |