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 gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Public Variable Not Found beyond MAIN program

Status
Not open for further replies.

SimplyES

Programmer
Oct 5, 2012
39
GB
I am having issues with what appears to be failing PUBLIC variables. I have read many threads over the last couple of days but none yet that seems to catch my problem - everything seems to be in place.

Initially, I started with a simple PUBLIC declaration followed by assigning values to two variables within the MAIN program (SNMain.prg). These are placed after all the SETs but before anything else - definitely before READ EVENTS.

PUBLIC gcUserProfile, gcProfileName
gcUserProfile = GETENV("USERPROFILE")
gcProfileName = UPPER(RIGHT(gcUserProfile, LEN(gcUserProfile) - tnCalculated_Number))

I know the two variables load correctly as they are used further on within SNMain. However, the first form called by SNMain declares that they are 'Variable not found'. To make absolutely sure I hadn't done anything dumb somewhere in the depths of the form's methods which was dumping the variables, I added a couple of lines right at the top of the INIT.

tnTemp1 = gcUserProfile
tnTemp2 = gcProfileName

The two Publics are already gone before these lines.

Next, I replaced the variable definition section with the following

PUBLIC oGV, gcUserProfile, gcProfileName
oGV = NEWOBJECT("snGlobals", "snClassLib")

The class, snGlobals, sets the two Public variables and, as before, these are available within SNMain - but not elsewhere. This is not different, of course, to what I did initially - just a different way of achieving it!

Whilst I still have some hair left, I would be really grateful if someone could point out what obvious thing I'm missing?
 
As far as I can see, you are not doing anything wrong. The public variables should indeed be available from within your form.

The only thing I can think of is that you are executing RELEASE ALL or CLEAR ALL or something similar, somewhere after you declare the variables but before you use them. Try using Code References to search for them.

If that doesn't help, you could try setting a breakpoint on one or both of the variables. Set it to "break when expression is true". That might give you some inkling as to what is going on.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Never thought I'd see the day when someone telling me "you are not doing anything wrong" would be a disappointment! However, you did go on to put your finger on the very (and as I suspected) obvious error. A [CLEAR ALL] lurking in amongst some recycled code further down in the MAIN program. Another case of the more you look the less you see. So, in the end life is back to normal ... I had done something wrong. I'm surprisingly comfortable with that.

Thanks Mike.
 
Well, look out for any RELEASE, RELEASE ALL, CLEAR ALL.
Before Form.Init comes Form.Load (remember LISA - load,init,show,activate).

Also see here: I suggest you don't define these variables as PUBLIC in main, you simply not declare them.
That makes them as good as public as they become private variables always on the call stack, as main.prg always is on the call stack.
The article says, that the same problem affects private variables, but the problem has a lesser impact.

So simply go back to your initial code and comment out the PUBLIC line.
Also investigate, if you ever pass the public variables in any call somewhere. That's obviously unnecessary but the variable passing mechanism obviously changes the state of the passed public variables.

Bye, Olaf.
 
This particular very small and stand-alone application is the only one on the devices so PUBLICs won't interfere elsewhere. However, no guarantee that will always be the case so the idea of removing the (unnecessary) PUBLIC declaration is a sound principle which I will adopt. Thanks
 
> so PUBLICs won't interfere elsewhere

I don't know why you say this. PUBLICs are only PUBLIC to your process anyway. PRIVATEs are only visible from the call stack level they are generated on and all called code. Since main.prg always is the first thing on the stack PRIVATE (undeclared) variables in main.prg are quasi PUBLIC.

Bye, Olaf.
 
I do not use public variables but rather use properties defined at _VFP level.

ADDPROPERTY(_VFP, "UserProfile", GETENV("USERPROFILE"))
ADDPROPERTY(_VFP, "ProfileName", UPPER(RIGHT(_VFP.UserProfile, LEN(_VFP.UserProfile) - tnCalculated_Number)))

These are always available and not a problem with the name being reused later in code as another variable. I have always wished that VFP had strict definition and scoping of variables like other languages such as C or java. I have never liked the behavior of VFP scoping of PRIVATE (and the variable defaulting to this scoping) which allows the variable to been seen outside of the method it was defined in when other methods are called. This leads to many bugs. LOCAL tries to stop this but if the variable is not defined as LOCAL it is PRIVATE in scope by default.
 
It'll be harder to change all code accordingly (I'm cautious with search&replace by Code REferfences, as it at least was flaky, if the replacement was longer than the searchtext)

The issue the wiki shows is, that by passing the global variable somewhere you turn it into a local or private thing and it becomes flaky to address it. You don't need to pass public variables, obviously, but some code might have started with passing a parameter later replaced with a property and even later with a public variable, then you still might have some older code now passing the public variable as parameter and that is what hurts in the scenario the wiki describes.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top