Home AMX User Forum NetLinx Studio

LOCAL_VAR v's STACK_VAR

Hi,
I have been given a task to update some of my colleagues Netlinx code.

I found that in most of is define_calls he has created a local_var?s called loop.

Eg:
DEFINE_CALL ?something?
{
LOCAL_VAR loop
..code..
}
DEFINE_CALL ?something 2?
{
LOCAL_VAR loop
..code..
}

Would it be better to convert these to STACK_VAR?s as this are not static once created?
Eg:
DEFINE_CALL ?something?
{
STACK_VAR loop
..code..
}
DEFINE_CALL ?something 2?
{
STACK_VAR loop
..code..
}

Regards
Craig

Comments

  • "It depends" :-)

    a LOCAL_VAR is working within a function block (Call, Function, but also i.e. in a CASE, PUSH of BUTTON_EVENT, etc). It will still hold its value if the if the function block if finished. It is hold in the nonvaltile memory of a master

    a STACK_VAR is working in most situations like a LOCAL_VAR, but will lost its value after the section is done. It is hold in the volatile memory of the master.

    There are some situations where by design a STACK_VAR will not work, i.e. if you need the value of the STACK_VAR in a WAIT. (the functions within the wait are stacked, but the stack_var content is lost because the function block of the code is finished). There are some more exceptions where a LOCAL_VAR must be used instead of a STACK_VAR (some by design, some more like a bug ;-)
  • DHawthorneDHawthorne Posts: 4,584
    I prefer to make my subroutine variables stack whenever I can. For one, you have far less non-volatile memory than volatile, and I have run out on big projects with a lot of modules. Second, stack variable reset to null every time the routine is called. Sure, you can just initialize it, but one line less code, is one thing less to worry about.

    Of course, there are time you need it to be a local. If the routine is tracking something that only it needs to know about, you probably want it to retain it's value. And, as mentioned, you must make any variable used in a wait a local.
  • ericmedleyericmedley Posts: 4,177
    I have to admit that I never use STACK_VARs or LOCAL_VARs

    DHawthorne wrote:
    I prefer to make my subroutine variables stack whenever I can. For one, you have far less non-volatile memory than volatile, and I have run out on big projects with a lot of modules. Second, stack variable reset to null every time the routine is called. Sure, you can just initialize it, but one line less code, is one thing less to worry about.

    Of course, there are time you need it to be a local. If the routine is tracking something that only it needs to know about, you probably want it to retain it's value. And, as mentioned, you must make any variable used in a wait a local.
  • AMXJeffAMXJeff Posts: 450
    Local Variables

    Functions should be designed to be some what portable. With this in mind, using Local_Vars to keep the last value is normally not the best practice. Although most programmer use Local_Vars and reset them at the beginning of each function. In this case Stack_Vars should be used. Stack_Vars allocate memory from the stack whenever the function is called, and at the end it de-allocates the memory. This tends to manage your memory better. If you truly need to retain the last value in the function, by all means use Local_Var. By doing this you tend to make the function less portable. I would suggest in this case passing global variables into the function, and let the function use the passed in variables. This way the function can be used for multiple object instances.

    The biggest plus for Local_Vars is you can actually watch them in debug. I tend to make them Local_Vars for testing, and then switch them back to Stack_Vars when the function is debugged. By the way you can actually watch Stack_Vars in debug, but only when you have a break point inside the scope of the Stack_Var. This is assuming you can actually get break points to work.
  • DHawthorneDHawthorne Posts: 4,584
    ericmedley wrote:
    I have to admit that I never use STACK_VARs or LOCAL_VARs

    The you are using LOCAL_VARs. That's the default if no explicit declaration is made. I generally try to make all my declarations explicit so there is no confusion what type of memory space is being used, or on the outside chance the default ever gets changed in the compiler.
  • Joe HebertJoe Hebert Posts: 2,159
    DHawthorne wrote:
    The you are using LOCAL_VARs. That's the default if no explicit declaration is made.
    Yes, that's what the help file states:
    If neither the LOCAL_VAR nor the STACK_VAR keyword is specified, LOCAL_VAR is assumed.
    However, I believe the help file is in error and is in fact the other way around. Consider the following code:
    DEFINE_DEVICE
    
    dvTP = 10001:1:0
    
    DEFINE_FUNCTION fnVarTest() {
    
       INTEGER 		a
       STACK_VAR INTEGER 	b
       LOCAL_VAR INTEGER 	c
       
       a++
       b++
       c++
       SEND_STRING 0, "'a=',ITOA(a),' b=',ITOA(b),' c=',ITOA(c)"
    }
    
    DEFINE_EVENT
    
    BUTTON_EVENT[dvTP,1] {
    
    
       PUSH: {
          fnVarTest()
       }
    }
    
    Pushing button 1 four times produces this output:
    Line 1 :: a=1 b=1 c=1 - 15:24:48
    Line 2 :: a=1 b=1 c=2 - 15:24:49
    Line 3 :: a=1 b=1 c=3 - 15:24:50
    Line 4 :: a=1 b=1 c=4 - 15:24:51

    The only variable that maintains its value is the variable that is explicitly declared as a LOCAL_VAR. If not specified, the variable is treated as a STACK_VAR.
  • mpullinmpullin Posts: 949
    DHawthorne wrote:
    ericmedley wrote:
    I have to admit that I never use STACK_VARs or LOCAL_VARs
    Then you are using LOCAL_VARs.
    Not necessarily. Maybe eric just never uses variables in his functions, for extra style points.
  • NMarkRobertsNMarkRoberts Posts: 455
    Joe Hebert wrote:
    The only variable that maintains its value is the variable that is explicitly declared as a LOCAL_VAR. If not specified, the variable is treated as a STACK_VAR.

    Nice work Joe.

    It actually makes more sense for it to default to stack_var on the principle of least surprise. Least surprise, that is, for anyone who is familiar with many other languages (your mileage may vary.)
  • ericmedleyericmedley Posts: 4,177
    mpullin wrote:
    Not necessarily. Maybe eric just never uses variables in his functions, for extra style points.

    ...Or maybe I don't use functions at all... There are other ways to do repetitive things.

    8~)
  • adysadys Posts: 395
    Something to be aware when using stack vars

    http://www.amxforums.com/showthread.php?t=2642

    in short - the stack var caused a debgging problems
  • REBUILD_EVENTREBUILD_EVENT Posts: 127
    and never forget:

    STACK_VAR CHAR Arrays[] are not empty, they are initialized with rubbish unless you assign something to them in this way
    Array='...'

    they are not cleared when you assign
    Array[1]=$2
    Array[2]=$0D
    and so on...

    wasted another afternoon because of that, even though i knew before....
    i already thought about using STACK_VAR CHAR Arrays as Randomizer...
  • DHawthorneDHawthorne Posts: 4,584
    and never forget:

    STACK_VAR CHAR Arrays[] are not empty, they are initialized with rubbish unless you assign something to them in this way
    Array='...'

    they are not cleared when you assign
    Array[1]=$2
    Array[2]=$0D
    and so on...

    wasted another afternoon because of that, even though i knew before....
    i already thought about using STACK_VAR CHAR Arrays as Randomizer...

    It's more likely they are just allocated, and whatever was in that memory space previously is what you are seeing. However, when stack arrays are initialized, they are initialized with a length of zero, and normal array operations would treat them as empty. It is because you are referencing individual elements that you are seeing anything at all: namely, whatever data is in that space. I suspect this is not limited to stack arrays, but any that is not initialized with an explicit value.
  • GSLogicGSLogic Posts: 562
    [QUOTE=However, when stack arrays are initialized, they are initialized with a length of zero, and normal array operations would treat them as empty.[/QUOTE]
    SET_LENGTH_STRING(String,0) will set the length to zero, but it does not clear the string value until it is reloaded. I was told, the processor looks at the String Length first, if over 0 then the value.
  • TurnipTruckTurnipTruck Posts: 1,485
    I beleive I once heard of something like an "Event Variable?" Is there a variable type that can be defined once at the top of an event and hold value through a PUSH, RELEASE and HOLD without redeclaration and initialization?

    Thanks
  • Jeff LockyearJeff Lockyear Posts: 147
    I don't think so ("event variable"), but that should definitely go in the suggestion box....

    Jeff
  • AMXJeffAMXJeff Posts: 450
    No such animal...
  • DHawthorneDHawthorne Posts: 4,584
    I beleive I once heard of something like an "Event Variable?" Is there a variable type that can be defined once at the top of an event and hold value through a PUSH, RELEASE and HOLD without redeclaration and initialization?

    Thanks

    I believe that refers to the built-in ones ... like BUTTON.INPUT.CHANNEL. I could be wrong; that was my understanding of it though.
  • GSLogicGSLogic Posts: 562
    I beleive I once heard of something like an "Event Variable?"
    I'll vote for the "Event Variable"
Sign In or Register to comment.