Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Trapping an untrappable error

Status
Not open for further replies.

rlawrence

Programmer
Sep 14, 2000
182
US
Hi folks,

I'm at that point, once again, where I seem to be at the end of my bag of trick and could use some new ideas.

I have a nagging "Datatype Mismatch" error that shows up under very specific conditions in my application. The error seems to have no consequence. Ignoring it allows the program to continue and all data is saved as expected. But the error is obviously disconcerting to the users.

The error occurs when exiting one form, and returning control to another, but ONLY if a particular action has taken place (involving a third form). Just to give you some context, the first form is a contact screen. The second is a customer profile screen, and the third form is a sales rep and commission rate screen. The action that causes the problem is the assignment of a new sales rep to a customer contact.

By the way, if you remain in the contact screen and move on to another record and again assign a new sales rep, the error does NOT occur.

This is too deep to expect anyone to look at my code or to try to present something that reproduces the problem. Rather, I wanted to ask for strategies for nailing this error down. I can't step through the code in the debugger and find a statement that generates the error. As best as I can tell, it occurs literally at the time control is returned to the DO FORM ... command for the first level Contact screen. F.Y.I. That line of code looks like this:

Code:
DO FORM "contact.scx" NAME cntct_form[cntctlevel] LINKED &_cparmstr TO m._rval

Yep! This is stuff that goes back to the conversion from Foxpro 2.6 to VFP 3. It's been working fine for 20 years!

A little more background: The contact screen can call itself. That's why the form is linked to a name held in the CNTCT_FORM[] array. At the point of the failure, the expressions used in this command are out of context. (The debugger shows "Expression can not be evaluated.") But this is the case when you look at these expressions while control is still in the called procedure. The debugger clearly doesn't refresh all of the watched expressions as I step through this process anyway.) I feel like I am already placing too much emphasis on this line of code, but wanted to provide as clear a picture as I could.

So, I have an error that pops up in a very particular place, under very specific conditions, but doesn't seem to be a specific line of code. I have tried using the event logger to see what events are firing between the last line of the called procedure and returning to the contact form. I have also used _VFP.LanguageOptions to check variable declarations to see if something is getting clobbered in a lower-level procedure. I have found nothing so far.

So, I am looking for new strategies to trap this error. I think after all these years that I know a little something about Foxpro. Then I run into a problem like this and feel like a complete idiot. Your thoughts would be appreciated.

Thanks,
Ron
 
Got it!

It was a SKIP FOR clause on a menu item in the Contact screen menu! The variable was M.SALES_REP. There's a good chance that gets clobbered in the Sales Rep Commission screen.

The thing that turned me on to this possibility might be worth sharing. Looking at the assignments to variables in my last post got me thinking about ways to identify what has changed. I wound up putting the following into my menu procedure that calls the customer profile screen.

Code:
DISPLAY MEMORY TO FILE precustomer.txt NOCONSOLE
DO customer.spr WITH m.contact_no
DISPLAY MEMORY TO FILE postcustomer.txt NOCONSOLE

I then used the FC utility to compare the resulting files. It helped me to zero in on the changed values in memory pretty well.

One significant difference was that there were popups still defined after returning from the customer profile screen--even though that form is supposed to restore the system menu. (i.e. POP MENU _MSYSMENU) That got me to focus on the menu procedures--rather than the context for the forms.

So, there's a another little trick to add to my bag. Maybe it will help someone else too. Again, thanks to all for your help. Just working through this with other developers really helps.
 
Delighted to hear you've solved it. In retrospect, we should have remembered earlier that a SKIP FOR clause is one of the places where an error can be triggered "outside the code" (like in a report). Something to keep in mind for the future.

By the way, I must commend you for your approach to the problem. Your first post in this thread was a model of clarity. You gave us the full picture, and we didn't have to keep asking for clarification. And it was good that you acknowledged and commented on each of the replies you received. This is a welcome change from the typical forum thread, where we spend longer trying to understand the problem than we do in solving it.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I second Mike,

the only thing a bit disturbing is lengthy log posts.

Congratulations!

And your mentioning of LanguageOptions reminded me of something very long ago. I just had a very faint memory on it as I once did a routine based on Chrisiof Wollenhaupts ISX.prg, which did add LOCAL declarations to code missing some at the top of the method/proc/function and one of the reactions to it was mentioning of this very sparsely discussed LanguageOptions.

Also, there are two very good uses of PRIVATE though, I won't groan about:

1. To repel all incoming private variables from any third party developer you can start any code with PRIVATE ALL or, as another good use PRIVATE ALL EXCEPT goApp.
Well, that's use of PRIVATE to prevent private vars, not to create them. It's just saying any private variable existing won't be used, if you accidentally miss a LOCAL declaration, instead you'd create a further new private var, which means you don't overwrite or use any incoming value from a caller. If applied everywhere, this makes any private a LOCAL.

2. In recursive functions you can use a variable without passing it on.
This is one good reason for actually using private vars themselves, not only the PRIVATE statement.

In this case, that can speed things up, as variable creation can take high execution time percentage of an otherwise very short code per recursion level. It saves using optional parameters, checking of PCOUNT(), VARTYPE() and more. You could even use the value of the previous recursion level up to some point. Then you do PRIVATE at that place, create a further private var of same name below and it's like a LOCAL var with the twist of being local to the second half of the current and the first half of the next recursion level.

Finally:

I don't get your logic, why any variable logged is proven to not be problematic, in fact I would say any variable logged could be a problem, instead any variable not logged surely is not private and could only be clobbered, if PUBLIC. Proof of the unlogic: SALES_REP is in your LanguageOptions log, see yourself:

LangOptionsErr,7/26/2013 3:42:26 PM,21,FRSCONTACT1.FRMCONTACT.LOAD,PROCEDURE FRSCONTACT1.FRMCONTACT.LOAD C:\USERS\RON\DOCUMENTS\MY DEVELOPMENT\PUBASSIST\CONTACT.SCT,SALES_REP

Bye, Olaf.
 
Thanks again guys. I use this service after exhausting myself on a problem. Since I'm asking for help, I hope, at least want, that the interaction will be useful to others.

Yeah, sorry about the long logs. Again, I put them here to complete the picture.

Olaf said:
I don't get your logic, why any variable logged is proven to not be problematic, in fact I would say any variable logged could be a problem, instead any variable not logged surely is not private and could only be clobbered, if PUBLIC. Proof of the unlogic: SALES_REP is in your LanguageOptions log, see yourself:

LangOptionsErr,7/26/2013 3:42:26 PM,21,FRSCONTACT1.FRMCONTACT.LOAD,PROCEDURE FRSCONTACT1.FRMCONTACT.LOAD C:\USERS\RON\DOCUMENTS\MY DEVELOPMENT\PUBASSIST\CONTACT.SCT,SALES_REP

I probably didn't complete the thought. Since this log was from the beginning of the session, then the offending variable was likely to be in there. But the assignment that caused the problem would NOT, because the variable was already declared. In this case, it was the Sales_Rep variable that was declared in the contact screen. The Sales Rep Commission screen obviously overwrites it. Not surprising, given the name. I'm afraid this dates back to the early 1990's when the database was defined. The use of datatype prefixes was not common to my knowledge back then.

Again, thanks for being there. Just explaining the problem to someone else who understands, and getting reactions all around is actually quite helpful.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top