I'm writing an ActiveX DLL in VB6. The DLL exposes a class of objects
that can be created through an ASP page. Some of the properties of
some of the objects are set "dynamically," that is, the Property Get
function runs a GetPropertyValue() function that gets the value for
the object's property from the database. This function uses the
CallByName() function to check whether the specified property is
currently populated, and uses it again to set the property value (I'm
using CallByName because it's a generic function that is supposed to
work with any object/property). The problem is that I keep getting an
"out of stack space" error on the line that calls CallByName(). The
line is:
varProperty = CallByName(CurrentObject, PropertyName, VbGet)
CurrentObject is the object that is being passed to the function, in
this case a "Content" object that I've created. PropertyName is a
string, also passed to the function, that indicates which property to
check. The code that calls the function in this case is:
Public Property Get ContentID() As Integer
ContentID = GetPropertyValue(Me, "ContentID")
End Property
As far as I can tell, this error means that I've nested my code too
deeply, but the function is only 4 levels deep. Any ideas would be
appreciated.
Rob Kroese - 31 Oct 2003 07:31 GMT
Ok, so I figured this about about 7 seconds after I posted the
message. The cause is pretty obvious, it turns out, but I'll post it
just so anyone else who tries this doesn't have to go through what I
did.
Yes, the problem is that referencing the property's value with
CallByName in the GetPropertyValue causes the app to run the
GetPropertyValue function, which calls the CallByName function, which
runs the GetPropertyValue function... Endless loop. In this case, an
infinitely deep stack, resulting in the stack space error.
You can avoid the problem by passing the local property value to the
GetPropertyValue function, so it knows what the existing value is
without using the Property Get.
Don't do drugs.
Kamilche - 31 Oct 2003 08:48 GMT
> ...The problem is that I keep getting an
> "out of stack space" error on the line that calls CallByName(). The
> line is:
That error usually indicates you've entered an endless loop. Without
seeing more of your program, I can't tell how or if that is happening.
But here's something else to think about: Do your properties always
return non-object values, or do they sometimes return objects? If they
ever WILL return objects, you'll have to do some fancy footwork to
allow for that, because manipulating objects in VB6 requires the use
of the 'Set' keyword.
Here's a little example I created to illustrate the problem.
Option Explicit
Private Function GetProperty(ByVal PropertyName As String, ByVal
Person As Object) As Variant
' You've got to know whether the property returns an object or
not!
' If so, you have to use 'set GetProperty = '.
' If not, you can use 'GetProperty ='
' You end up getting the property twice this way, once to see if
' it's an object or not, and another to actually get it.
' You could rewrite it as in the 'LookupProperty' subroutine
below.
If IsObject(CallByName(Person, PropertyName, VbGet)) Then
Set GetProperty = CallByName(Person, PropertyName, VbGet)
Else
GetProperty = CallByName(Person, PropertyName, VbGet)
End If
End Function
Private Sub LookupProperty(ByVal PropertyName As String, ByVal Person
As Object, ByRef ReturnData As Variant)
' This method doesn't check the object to see whether or not
' it's an object, it checks the ReturnData instead.
If IsObject(ReturnData) Then
Set ReturnData = CallByName(Person, PropertyName, VbGet)
Else
ReturnData = CallByName(Person, PropertyName, VbGet)
End If
End Sub
Private Sub Command1_Click()
Dim person1 As clsPerson
Dim person2 As clsPerson
Dim o1 As Object
Dim o2 As Object
Dim n1 As String
Dim n2 As String
Set person1 = New clsPerson
person1.Name = "Fred"
Set person2 = New clsPerson
person2.Name = "Wilma"
Set person1.Spouse = person2
Set person2.Spouse = person1
' Use a function to return the value
Set o1 = person1
n1 = GetProperty("name", o1)
Set o2 = GetProperty("spouse", o1)
n2 = GetProperty("name", o2)
MsgBox _
"Object 1: " & Hex(ObjPtr(o1)) & " Name: " & n1 & vbCrLf & _
"Object 2: " & Hex(ObjPtr(o2)) & " Name: " & n2
Set o1 = person2
n1 = GetProperty("name", o1)
Set o2 = GetProperty("spouse", o1)
n2 = GetProperty("name", o2)
MsgBox _
"Object 1: " & Hex(ObjPtr(o1)) & " Name: " & n1 & vbCrLf & _
"Object 2: " & Hex(ObjPtr(o2)) & " Name: " & n2
' Use a subroutine to return the value
Set o1 = person1
LookupProperty "name", o1, n1
LookupProperty "spouse", o1, o2
MsgBox _
"Object 1: " & Hex(ObjPtr(o1)) & " Name: " & n1 & vbCrLf & _
"Object 2: " & Hex(ObjPtr(o2)) & " Name: " & n2
Set o1 = person2
LookupProperty "name", o1, n1
LookupProperty "spouse", o1, o2
MsgBox _
"Object 1: " & Hex(ObjPtr(o1)) & " Name: " & n1 & vbCrLf & _
"Object 2: " & Hex(ObjPtr(o2)) & " Name: " & n2
End Sub
And here's the code in clsPerson (a contrived example, you'd probably
never want to set the spouse as an object instead of an ID number):
Option Explicit
Private mName As String
Private mSpouse As clsPerson
Public Property Let Name(ByVal value As String)
mName = value
End Property
Public Property Get Name() As String
Name = mName
End Property
Public Property Set Spouse(ByVal value As clsPerson)
Set mSpouse = value
End Property
Public Property Get Spouse() As clsPerson
Set Spouse = mSpouse
End Property
Kamilche - 31 Oct 2003 08:54 GMT
I misspoke on my first reply. It's not the sign of an endless loop,
but rather, too much recursion, a subtle difference! An example would
be a function that calls itself repeatedly, or calls another function
that ends up calling the first function. A different kind of 'endless
loop.'
And there was a slight bug in the code I posted. Add the following
lines to the last two blocks of statements, just before the 'MsgBox'
statement.
LookupProperty "name", o2, n2
Should have reviewed it more carefully before I hit the 'Post Message'
button, sorry about that.