INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Jobs

PEMSTATUS bug

PEMSTATUS bug

(OP)
I am victim of a bug I just found. Unfortunately of course it happens in a project, where it is important, but take that aside, I can cope with the aftermath...

CODE

o = CREATEOBJECT("nested")
? PEMSTATUS(o,"inner1",5)
? VARTYPE(o.inner1)
? TYPE("o.inner1")
? o.inner1.name

DEFINE CLASS nested as Container
   ADD OBJECT inner1 as innercontainer 
ENDDEFINE    

DEFINE CLASS innercontainer  as Container
   PROCEDURE Init()
      RETURN .F.
ENDDEFINE 

The PEMSTATUS says the inner1 object exists, yet it does not due to RETURN .F. from init. In the real world case, this is not that simple of course, there are condition checks, that may or may not lead to a subobject removing itself from a compound class. In my case it's a visual class, but it doesn't matter, the problem also exists in PRG.

I assume this bug is "by design", the inner1 clearly is a member of the class definition of nested, so it is a defined member, it is just not existing at runtime.

To overcome the issue I had to replace PEMSTATUS calls to TRY CATCH statements making use of the probably not existing sub object. As Vartype and Type also tell this unknown element is of type "O" (object), you can't do any precheck as caution about using such an object. Also the locals window will list "inner" as a node of the "o" object, if you start the debugger after creating o. So actually this most probably is no bug of the PEMSTATUS function itself, but of how objects and information about them are managed by VFP.

I wouldn't consider this a serious bug simply by seeing how many VFP software still works, as it may not make much use of such situations, but classes already put together at design time that eventually remove some of their inner components may cause trouble. And this time it's not about the infamous "zombie" objects as dangling object references are sometimes called, that remain if objects are not released correctly. RETURN .F. from init is a correct way of saying you don't want the object to become alive at all. Any objects init finally decides about it's existence with the .T. or .F. return value, .T. is just a default you don't even have to write into the code as RETURN .T.

Bye, Olaf.

RE: PEMSTATUS bug

Weird one Olaf. I use PEMSTATUS for several things, I guess usually I don't remove objects in the middle of object chain, but will try to keep this in mind.

Best Regards,
Scott
ATS, CDCE, CTIA, CTDC

"Everything should be made as simple as possible, and no simpler."hammer

RE: PEMSTATUS bug

It's kinda creepy, but the object inner1 exists, although we can't do anything with it.

Since its initialization failed, none of the properties and methods of its class are going to be instantiated (because the parent wasn't, also). So, asking for o.inner.name will raise an error, but asking for o.inner won't, which will make this all thing at least consistent.

Checking for a living object will require looking into the availability of its properties, but - correct me if I'm wrong - PEMSTATUS() with flags 1 to 6 refers to a class definition of an object, not to the status of an instantiation. That is, it should be used to verify if a property, event, or method was (re)defined for the class of an object, and not to check if the class was instantiated or not as an object.

Instead of PEMSTATUS(o, "inner1", 5), TYPE("o.inner1.name") != "C" would do for the checking. Or, better still, in my view, if the "nested" object operation requires "inner1", then it should be "nested"'s responsibility to check for "inner1"'s availability, and its own Init fail if the contained didn't get instantiated.

CODE --> VFP

DEFINE CLASS nested as Container
  ADD OBJECT inner1 as innercontainer
  
  FUNCTION Init
  	RETURN TYPE("This.inner1.name") = "C"
ENDDEFINE 

RE: PEMSTATUS bug

I'm not sure I'd label this a bug. It's sort of in line with this behavior:

CODE

o = CreateObject("form")
o.Release()
?Type('o')  && "O"
?0  && .NULL. 

It's there but it really isn't.

RE: PEMSTATUS bug

(OP)
I did PEMSTATUS(o,"inner1",5).

It's true, that the encapsulation principle should mean you never address more than the outer level from outside. But then is it really wrong, if a form method acts on a contol inside a container? or pageframe or grid? This inner object is an adapter for a COM server, which in turn manages a smartcard. If the smartcard is not inserted, the initialization finds out and the software has to work in a reduced mode.

The problem appears in several validation calls checking the current situation and that's where it becomes a little blurry whcih class and object instance should really do what to control and validate and check each other.

I think a little refactoring would have meant to only deal with the problem in a single place instead of now - let me lie - about 5 places. Not all that bad. I also thnk about returning .T. in any case and inactivating it with another property quite like Enabled or Visble is doing for controls.

I also get your point, dan, but at least you can get 'X' from Vartype(o) and know you have a certain state.

Bye, Olaf.

RE: PEMSTATUS bug

(OP)
I kind of agree it's by design of PEMSTATUS, as 5 says Defined property, event, method, or object, and it is defined.

But the problem actually is not about the core PEMSTATUS meaning, but about not being able to find out before erroring. So I think TRY..CATCH is a workaround.

Of these alternative also only TYPE really works:

CODE

? PEMSTATUS(o.inner1,"name",5)
? VARTYPE(o.inner1.name)
? TYPE("o.inner1.name") 
The Vartype call errors, too, though a simpler VARTYPE call just like TYPE do not depend on the existence of the given name, eg ? VARTYPE(sdfhjkdshfjkh) yields "U", whereas ? sdfhjkdshfjkh triggers error "Variable ... not found".

So finally a workable solution is to test for a known property of the subobject via TYPE, if you don't like the TRY..CATCH approach.

Bye, Olaf.

RE: PEMSTATUS bug

Does checking ISNULL(o.inner1) work?

Tamar

RE: PEMSTATUS bug

(OP)
You can check with the sample repro code: No,that returns .F.

See several results:

The TYPE("o.inner1.name") is the only really helpful value to detect the situation.
The line the debugger points to will error.

The debugger itself, as said, shows the inner1 node as Type O, too, but no [+] expand symbol aside of it, which every real object would show, so the debugger knows more than it shows, it could show "U" as it knows there are no PEMS, and that's impossible with a real object.

Bye, Olaf.

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!

Resources

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close