Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion GroupsVB SyntaxEnterprise DevelopmentDatabase AccessControlsCOMWin APICrystal ReportDeploymentGeneralGeneral 2
Related Topics
VB.NET / ASP.NETMS SQL ServerMS AccessOther Database ProductsMore Topics ...

VB Forum / General 2 / October 2003



Tip: Looking for answers? Try searching our database.

CallByName() causes "out of stack space" error

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Rob Kroese - 31 Oct 2003 04:33 GMT
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.
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.