Microsoft Office Forums

Go Back   Microsoft Office Forums > Microsoft Excel > Excel Programming

Reply
 
LinkBack Thread Tools Display Modes
  #46  
Old 06-23-2014, 04:54 PM
whatsup whatsup is offline Windows 7 64bit Office 2010 32bit
Competent Performer
 
Join Date: May 2014
Posts: 137
whatsup will become famous soon enough
Default

O_o, quite interesting

May I ask you a few questions about your new function of the last upload?


1.
Code:
Public Const coBytes As Long = 4 * 8
You changed to 32 Bytes, just for purpose of demonstration or is there any particular reason?
2.
Quote:
The routine is called Mem_ReadHex_Words. It also allows for 4, 8 or 16 bit words which are required by some data structures.
That's still the problem, that we don't know what data-structure we're really facing, isn't it?
3.
Curiousity - I've never seen this before:
Code:
wordCount = Length \ wordLength
For divisions I use / you as well as I see in the following line. Therefore I wonder what's the joke on this?
Reply With Quote
  #47  
Old 06-23-2014, 07:41 PM
CoolBlue's Avatar
CoolBlue CoolBlue is offline Windows 7 64bit Office 2013
Advanced Beginner
 
Join Date: Jun 2014
Location: Australia
Posts: 40
CoolBlue is on a distinguished road
Default Slow "comparison/replace" script

Quote:
Originally Posted by whatsup View Post
O_o, quite interesting

May I ask you a few questions about your new function of the last upload?
1.
Code:
Public Const coBytes As Long = 4 * 8
You changed to 32 Bytes, just for purpose of demonstration or is there any particular reason?
The main reason is that the object structures are generaly more than one worrd so I wanted to see what was there in the structure to see if I could notice any patterns now that the byte order is fixed.
The Mem_Read for VarPtr is still set to 4 (it should be set to POINTER_LENGTH in fact).
Quote:
Originally Posted by whatsup View Post
2.
That's still the problem, that we don't know what data-structure we're really facing, isn't it?
Well, the data structures are interesting but not relevant to the test we are doing. But anyway, we now have a method for seeing the data properly (not scrambled by endian coding) so we can look at some standard structures like VB Variant structure for example to see if we can get some clue.
The main point is that we can confirm the relationship between VarPtr and ObjPtr for objects. We can confirm that the Loal Object, is just a LongPtr containing the address of the referenced object or zero, depending on if its been set or not.
Before I unscrambled the bytes, it was not obvious that the Mem_Read from VarPtr was in fact the address of the global object. But now we are clear on that.
So, using your Mod01 as an example, it means that we can say with 100% confidence that, after runtime:
If Mem_ReadHex_Words(lng_objPtr, 4) = 0 then
objwks is set to Nothing

If Mem_ReadHex_Words(lng_objPtr, 4) = ObjPtr(Sheet1) then
objwks has not been properly released

If Mem_ReadHex_Words(lng_objPtr, 4) <> ObjPtr(Sheet1) then
objwks has been properly released

Thus solving the problem that you raised earlier about ObjPtr returning the same thing for the local and global variables.
Quote:
Originally Posted by whatsup View Post
3.
Curiousity - I've never seen this before:
Code:
wordCount = Length \ wordLength
For divisions I use / you as well as I see in the following line. Therefore I wonder what's the joke on this?
/ is divide and \ is div or integer divide
Run this code...
Code:
Sub testIntDiv()
Debug.Print 3 / 5
Debug.Print 3 \ 5
End Sub
I use it like this:
if p / q = p\ q then p is divisible by q

Last edited by CoolBlue; 06-24-2014 at 07:30 PM.
Reply With Quote
  #48  
Old 06-24-2014, 06:03 PM
whatsup whatsup is offline Windows 7 64bit Office 2010 32bit
Competent Performer
 
Join Date: May 2014
Posts: 137
whatsup will become famous soon enough
Default

Thanks, for the explanations

I agree and I'm delighted that your function Mem_ReadHex_Words shows the relation to HexPtr(ObjPtr) clearly now.
On the proof for the release of memory I also agree, though it's more complicated as you showed:
Quote:
If Mem_ReadHex_Words(lng_objPtr, 4) = ObjPtr(Sheet1) then
objwks has not been properly released

If Mem_ReadHex_Words(lng_objPtr, 4) ObjPtr(Sheet1) then
objwks has been properly released
Actually:
If Mem_ReadHex_Words(lng_varPtr, 4) doesn't point anymore to
HexPtr(lng_objPtr, 4)
And
Mem_ReadHex_Words(lng_objPtr, 4) <> Mem_ReadHex_Words(ObjPtr(Sheet1))
should proof that memory has been released. (But that's just for the record, I think you meant the same)


Quote:
The Mem_Read for VarPtr is still set to 4 (it should be set to POINTER_LENGTH in fact).
Yes, I was setting it to 4 knowing the value (for objects) has to be in the range of Long. I didn't intend to test anything else with the tool.

Therefore, all we have to do: Thinking up a routine where reference count fails
Reply With Quote
  #49  
Old 06-24-2014, 07:42 PM
CoolBlue's Avatar
CoolBlue CoolBlue is offline Windows 7 64bit Office 2013
Advanced Beginner
 
Join Date: Jun 2014
Location: Australia
Posts: 40
CoolBlue is on a distinguished road
Default Slow "comparison/replace" script

Quote:
Originally Posted by whatsup View Post
On the proof for the release of memory I also agree, though it's more complicated as you showed:
Actually:
If Mem_ReadHex_Words(lng_varPtr, 4) doesn't point anymore to
HexPtr(lng_objPtr, 4)
And
Mem_ReadHex_Words(lng_objPtr, 4) Mem_ReadHex_Words(ObjPtr(Sheet1))
should proof that memory has been released. (But that's just for the record, I think you meant the same)
Yep, thanks for pointing that out, I left out the in my post and have now corrected it.

Quote:
Originally Posted by whatsup View Post
Yes, I was setting it to 4 knowing the value (for objects) has to be in the range of Long. I didn't intend to test anything else with the tool.

Actually I thought it was me who changed your code and left the 4 there

Im building a class module now to encapsulate this stuff to make it more convenient to deploy. I have some problem related to the need to pass the variable/object into the class as a variant type, i need to make sure the original address is available inside the class, so I just need solve that. I guess its got something to do with decoding the Variant Type structure but the Bytecomb site is very helpful on that, so shouldn't be a problem i think...
Reply With Quote
  #50  
Old 06-25-2014, 07:59 AM
whatsup whatsup is offline Windows 7 64bit Office 2010 32bit
Competent Performer
 
Join Date: May 2014
Posts: 137
whatsup will become famous soon enough
Default

I see your correction, but you still left out an important thing:
Quote:
If Mem_ReadHex_Words(lng_varPtr, 4) doesn't point anymore to
HexPtr(lng_objPtr, 4)
That's especially important for object-variables which are set to an object like "As Worksheet". That's because the lng_ObjPtr we obtain from objwks is the same as we get from ObjPtr(Sheet1). Since Sheet1 still exists when we check afterwards, it doesn't tell if the reference hold by VarPtr(objwks) has been released.

I have to come back on the example in my file for Run11_clsTest(). It actually doesn't show that the class got destroyed. I made an attempt to obtain the VarPtr and ObjPtr for Class1, but it didn't work therefore I left it. Now I figured it out:
Class1:
Code:
Public Sub Class_Initialize()
     Debug.Print "Class1 is initialized"
    
lng_objcls1 = ObjPtr(Me)
lng_varcls1 = VarPtr(Me)
    pointerToSomething "objClass1", lng_varcls1, lng_objcls1, coBytes
 End Sub
I still don't know why
Code:
lng_objcls1 = ObjPtr(Class1)
isn't accepted, but with "Me" it works.
Checking on these datas afterwards, it shows properly that the class gets terminated:
Mod11_Class:
Code:
Sub Run11_clsTest()
 Do_Header "Running Test_Class..."
Test_Class
    DoEvents
    Debug.Print "After Runtime"
    pointerToSomething "objcls1", lng_varPtr, lng_objPtr, coBytes
    pointerToSomething "objClass1", lng_varcls1, lng_objcls1, coBytes
    
End Sub
Quote:
Im building a class module now to encapsulate this stuff to make it more convenient to deploy....
I don't get what exactly you are after, but I guess you will surprise me again
Reply With Quote
  #51  
Old 06-25-2014, 08:57 AM
CoolBlue's Avatar
CoolBlue CoolBlue is offline Windows 7 64bit Office 2013
Advanced Beginner
 
Join Date: Jun 2014
Location: Australia
Posts: 40
CoolBlue is on a distinguished road
Default

Quote:
Originally Posted by whatsup View Post
I see your correction, but you still left out an important thing:
That's especially important for object-variables which are set to an object like "As Worksheet". That's because the lng_ObjPtr we obtain from objwks is the same as we get from ObjPtr(Sheet1). Since Sheet1 still exists when we check afterwards, it doesn't tell if the reference hold by VarPtr(objwks) has been released.
Yes, I see what you mean... I got myself confused trying to explain it. Unfortunately my time to edit it has expired already.
Quote:
Originally Posted by whatsup View Post
I have to come back on the example in my file for Run11_clsTest()....
I still don't know why
Code:
lng_objcls1 = ObjPtr(Class1)
isn't accepted, but with "Me" it works.
Its because Class1 is not an object, its a Class template if you like.
ObjPtr(Class1) is like VarPtr(LongPtr) or ObjPtr(Collection)
These are semantic representations of definitions of data structures, not objects. But, yep, that is what the Me statement is for. It refers to the particular instance of the object of type Class1. So every instance of type Class1 has its own "Me"... a pointer to itself. But a Class cannot have a pointer to itself, coz it's not an object, only a definition of a type of object.

I'n not sure what VarPtr(Me) is though... I can't figure that on out and the contents of that location are zero. That one is making my head spin

Quote:
Originally Posted by whatsup View Post
I don't get what exactly you are after, but I guess you will surprise me again
Well, we will see... I'm struggling with it.
I am hoping to have something like this...
Code:
Sub testObj()
Const objBytes As Long = 32
Dim o As clReferrence
Dim lObj As Worksheet

    Set gwks = Worksheets(1)
    
    Set lObj = gwks
    Set o = New clReferrence
    o.initObject objBytes, lObj
    
    Debug.Print "Address:  " & o.Address & vbTab & "Contents:  " & o.Contents
    Debug.Print "pAddress: " & o.pAddress & vbTab & "pContents: " & o.pContents

End Sub
But its hard to pass a reference to lobj (in other words VarPtr(lobj)) into the clReferrence object. VBA tends to resolve the reference all the way to gwks and the address of the local variable is discarded when you pass it into the Class Object.
Reply With Quote
  #52  
Old 06-25-2014, 04:48 PM
whatsup whatsup is offline Windows 7 64bit Office 2010 32bit
Competent Performer
 
Join Date: May 2014
Posts: 137
whatsup will become famous soon enough
Default

Quote:
These are semantic representations of definitions of data structures, not objects. But, yep, that is what the Me statement is for. It refers to the particular instance of the object of type Class1
Yes you're right of course, I missed that one instead was trying to treat the class as any class else (UserForm, Chart-Sheet, ...).

Quote:
I'n not sure what VarPtr(Me) is though... I can't figure that on out and the contents of that location are zero. That one is making my head spin
Interesting observation, but probably related to what you said above. Still we can make it visible, what's going on:
Code:
Private Sub Test_Class()
Dim objcls1 As Class1
    
Set objcls1 = New Class1
lng_objPtr = ObjPtr(objcls1)
lng_varPtr = VarPtr(objcls1)
    
    pointerToSomething "objcls1", lng_varPtr, lng_objPtr, coBytes
'Since VarPtr(Me) obtained in the class shows Zero check again:
    pointerToSomething "objClass1", lng_varcls1, lng_objcls1, coBytes

 Set objcls1 = Nothing

 If objcls1 Is Nothing Then
    Debug.Print vbTab & "Object is set to nothing"
Else
    Debug.Print vbTab & "Object wasn't cleared before leaving Sub"
End If
     pointerToSomething "objcls1", lng_varPtr, ObjPtr(objcls1), coBytes
    
End Sub
On the debug-print you can see that the Initialize-Event is triggered on
Code:
Set objcls = New Class1
but objcls isn't yet set. The class is assigned a pointer, whereas the VarPtr at this stage doesn't point anywhere but Zero, but the ObjPtr contains the vtable (methods, ...) of Class1 (and whatever else comes with the class).
With ObjPtr(Me) established objcls next is assigned a pointer VarPtr which points to the instance of Class1, and at this stage also VarPtr(Me) gets the reference. Pretty sure it's just a inside thing why it is like that. One explanation might be, that this way, in case the Set of objcls fails it's easier to release memory (but that's just a home-made explanation).

But as you already said some time ago, this part isn't that important. In the moment I'm doing some examples with various objects. When it comes to charts, that's rather confusing. It's somehow weird, which pointer (VarPtr) suddenly points to another object, though I expect it pointing to yet another object.
But that's only a thing of memory management, and we don't have to dive deeper, as long at the end the references show that they got removed.

As for the other part:
I leave you struggling, assuming if you don't get it working I won't either. The snippet of the code anyway leaves too much to guess.
Reply With Quote
  #53  
Old 07-09-2014, 07:00 AM
CoolBlue's Avatar
CoolBlue CoolBlue is offline Windows 7 64bit Office 2013
Advanced Beginner
 
Join Date: Jun 2014
Location: Australia
Posts: 40
CoolBlue is on a distinguished road
Default

errmm... back to this thoroughly hijacked thread...

I was doing some other stuff for a while, but I haven't forgotten about this...

I made a tool to parse the memory structure of these objects and I can show a map of what is going on in your Mod02_objRange module...

When you measure these structures, you need to make sure you take a snap shot of everything at the same time, otherwise they will get out of phase as the stack moves around. For example, if you read VarPtr in your Test_rng routine and then do the MemRead in PointerToSomething, it will be wrong because the location of the variable has popped further up the stack after the call.

But, if you take a snap shot of everything, then, even if they start from different addresses, they will resolve back to the object.

The second complication you get when you call a routine to do the measurements, is that new variables are created along the way, extending the chain of pointers back to the object. And if this is not confusing enough, some of the scalar references are wrapped into "Variant References". You can read about these in your Byte Comb site...

If you are dealing with objects (Range objects for example) and you see 00000009 or 00004009 at the location pointed to by VarPtr(object), then it is the first frame of a 4 word variant structure and the actual value (if its a pointer) is in the 3rd word of the structure, so you have to add 8 (4 bytes) to your VarPtr(obj) value to find the actual contents.
And even more confusing, the 4 flags it as a "By Ref Variant", meaning that the 3rd word points to a pointer to the actual value.

You can follow this in the attached snap shot. The top half is the results of my tool, and the bottom half is the readings that you would get from your PointerToSomething. The starting point of the pointer chains is different because they are floating up and down the stack, but, after you unravel these complexities, they always resolve back to the same object.

Although its useful for investigating the memory structure, the range object is not a useful example for checking garbage collection since no object structures are created... there are only references to global Range Objects which are not part of VBA's garbage collection. When I get time I'll continue on with this tool to use it on relevant examples.
But anyway, you said the Range objects were acting strange so maybe this will clear that up...
Attached Images
File Type: jpg Range.jpg (152.6 KB, 13 views)
Reply With Quote
  #54  
Old 07-27-2014, 10:57 AM
whatsup whatsup is offline Windows 7 64bit Office 2010 32bit
Competent Performer
 
Join Date: May 2014
Posts: 137
whatsup will become famous soon enough
Default

Hi CoolBlue

Sorry, it took me longer as I told in the PM.
Now, that seems to become a fulltime job - I'm not sure if I can summon up that time.

I studied your pic now for quite a while and wonder how serious you're about the reference of
rawSheets(1).Range("A1") and
rawSheet1.Range("A1")
Be aware that though basically it's the same object, the references or pointers may differ. Sheets(1) is an object of a spreadsheet relative to its position in the workbook whereas Sheet1 is a - you may say - static object within a workbook.
I don't know if it is the right thing to put it, but to explain it more visually:
For Sheets(1): Is assigned a pointer, which itself points to the object Sheet1. To say there are 2 pointers necessary.
Sheet1 instead, as it is the end of the line of objects, only needs 1 pointer.
So don't get confused, if the two cases show different pointers.


Quote:
I made a tool to parse the memory structure of these objects and I can show a map of what is going on in your Mod02_objRange module...
What you mean with this? You can't probably monitor the entire memory, can you?

I think the key would be to know about the structure of an object. Unfortunately the CombSite stops before he comes to this. On purpose? I can imagine, that the structure is quite difficult. Probably even containing references to various pointers, which all together only forming an object?

Quote:
Although its useful for investigating the memory structure, the range object is not a useful example for checking garbage collection since no object structures are created... there are only references to global Range Objects which are not part of VBA's garbage collection
I basically agree on this one. The objects exist in memory and those don't get destroyed as long the objects themselves are alive, all what matters: Do the references to these objects get destroyed, and that of course is the job the garbage collector has to perform. Now, in case you're right that the stack gets moved around all the time, it will be difficult if not impossible to keep track of these movements. But I hardly can imagine that this is the case. It would mean unnecessary efforts for systems to keep track of these movements for itself.
I rather imagine memory like a town, there are districts (which get assigned to a program as excel), within the district there are streets containing numbers (pointers) which hold the references. An inhabitant (value/object/whatsoever) either lives their (during runtime) or get moved out (by the garbage collector, or by setting it to nothing in case of objects)

That would lead us back to us establishing: A pointer (varPtr) contaning any other information as during runtime, allows the conclusion that references got destroyed and memory is freed.
Reply With Quote
Reply
Please reply to this thread with any new information or opinions.

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


All times are GMT -7. The time now is 09:44 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
MSOfficeForums.com is not affiliated with Microsoft