5

I'm trying to understand what dictates the lifetime of different bits of data; how the VBA interpreter knows it is safe to release the associated memory of a given variable. Here's what I've found so far:

Value types

Simple value types use scope to determine lifetime; e.g. a Long that is Dimmed inside a Function will hang around until an Exit/End * statement is hit. At this point the exact mechanism is unclear to me, but I imagine the VBA interpreter keeps a list of all variables in a given scope, and uses VarPtr and LenB to release all memory associated with them.

Object types

Objects meanwhile all derive from the IDispatch interface which is based on the COM IUnknown interface. As a result, objects use reference counting to determine lifetime. So a variable which holds a reference to an object (basically a LongPtr) will be overwritten when it falls out of scope (similar to value types), but just before that happens, the VBA interpreter calls IUnknown_Release on the IUnknown interface of the object (or more precisely, whatever interface is being held in the variable/With block).

As such, it is the responsibility of the COM object to clean up and release its own instance memory whenever the reference count drops to zero

Other Reference types

There are other reference types though (that is, types which are not stored as raw data like Doubles and Longs, but instead as pointers to the full data elsewhere). e.g:

  • Strings
  • Arrays
  • UDTs
  • Anything passed ByRef

Now since these are not strictly value types, VBA can't just use scope to determine lifetime; let's suppose some function Dims an array, which falls out of scope when the function Ends. Well if it is VBA's default behaviour to call SafeArrayDestroy on the array pointer then the memory would be freed as soon as the variable is out of scope. However what happens if the array is the return value of the function - now VBA can't free the underlying data when the variable is out of scope or things will break. If the array doesn't use reference counting, then how does VBA know to release it or not?

Similarly for the other types - any clue what exactly determines lifetime of these half value half reference types (they all are assigned without the Set operator so I guess they are not strictly reference types)

Community
  • 1
  • 1
Greedo
  • 4,967
  • 2
  • 30
  • 78
  • 1
    .NET type semantics do not apply to VBA. Strings and arrays are not reference types. When you assign, say, an array to another variable of an array type then you make a copy. Same for strings and UDTs. The basic reason why you get [this error message](https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/array-argument-must-be-byref), too expensive. Function return values and ByRef parameters are the caller's concern. – Hans Passant Feb 06 '20 at 19:28
  • @HansPassant ah, I knew about this behaviour for strings, didn't know it was true for arrays and UDTs too - I suppose that means they perform a deep copy on assignment (if you have an array of arrays for example)? Yes now I think about it ByRef variables and function returns are declared in the scope of the caller so that makes sense. Funny you should get that error message even though Let assignment with `=` is still allowed; if you really want ByVal a then you can just do b=a: ByRef b – Greedo Feb 25 '20 at 09:11

0 Answers0