Announcement

Collapse
No announcement yet.

Bug in PB DLL v 6 GLOBAL/DIM?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Bug in PB DLL v 6 GLOBAL/DIM?

    This is interesting enough that in addition to the note I sent to the support department, I thought I'd add it here.

    If it messed me up, it might mess up someone else, too:

    #IF 0
    ' NAME Test4.bas
    ' Demo of Bug IN compiler NOT finding GLOBALs
    8.20.99
    #ENDIF

    #COMPILE EXE
    #DIM ALL

    GLOBAL Qwerty AS ASCIIZ * 80

    FUNCTION PBMAIN()AS LONG
    DIM Qwerty AS LONG
    Qwerty = 2 '<<< Not cool for a GLOBAL ASCIIZ
    LOCAL H AS STRING
    H = "Hello World"
    MSGBOX H
    END FUNCTION

    Seems to me when I try to DIM Qwerty AS LONG inside of PBMain, I should get an error:

    466 Duplicate name definition - A SUB name, FUNCTION name, label name, or
    variable name was defined more than once in your code. Check your program
    and any include files for duplicate names and change one or both of them.

    Or am I missing something?

    MCM














    Michael Mattias
    Tal Systems Inc. (retired)
    Racine WI USA
    [email protected]
    http://www.talsystems.com

  • #2
    Michael --

    The default variable type is LOCAL, so when you do this...

    Code:
    DIM Qwerty AS LONG
    ...you are saying "I want to create a LOCAL variable called Qwerty". If you change that line to...

    Code:
    DIM Qwerty AS LOCAL LONG
    ...your code still compiles. But if you do this...

    Code:
    DIM Qwerty AS GLOBAL LONG
    ...the compiler produces an error. "String Operand Expected", on the Qwerty = 2 line.

    LOCAL variable names are allowed to "conflict" with GLOBAL variable names, if that is what you tell the compiler you want to do.

    IMO this is not a bug unless you want to argue that, when AS GLOBAL is used, the error should be tripped on the DIM...AS LONG line instead of elsewhere. But why do that, if the Qwerty variable is never actually used, i.e. if the errant DIM is there but Qwerty is not actually used as a LONG. The error should be tripped when the compilation can no longer continue.

    The bottom line is that the code that you posted looks perfectly valid to me... You just left out part of the optional syntax, and the compiler used a default variable type.

    -- Eric



    [This message has been edited by Eric Pearson (edited 08-20-99).]
    "Not my circus, not my monkeys."

    Comment


    • #3
      "IMO this is not a bug unless you want to argue that, when AS GLOBAL is used, the error should be tripped on the DIM...AS LONG line instead of elsewhere."

      That's exactly what I wish to argue.

      Your answer agrees with the official answer I received, namely, that LOCAL declarations override GLOBAL declarations.

      Now this is truly weird. It's as though the GLOBAL statment is somehow ignored as a scanned statement. I have never seen this in any BASIC or COBOL compiler. (Well, I guess now I've seen it in one compiler).


      " But why do that, if the Qwerty variable is never actually used,"

      The error actually occurred in a 1000-line program. I wrote this just to see if my mind had been playing tricks on me. I was setting (what I thought) a GLOBAL variable, but it was not changing. Turns out I was changing a LOCAL same-named variable of the same type. Yes, I made an error; but the compiler did not trap it for me. Kinda shoots all to snot the advantages of #DIM ALL, doesn't it?

      Bottom line, the PB/DLL compiler does not check for name conflicts on global variables; IMO a major deficiency which should be added to the next version, probably as an option for backward compatibility, i.e,

      #NAMECHECK ON

      or something like that.

      MCM


      [This message has been edited by Michael Mattias (edited 08-20-99).]
      Michael Mattias
      Tal Systems Inc. (retired)
      Racine WI USA
      [email protected]
      http://www.talsystems.com

      Comment


      • #4
        Michael --

        > It's as though the GLOBAL statment is somehow ignored as a scanned statement.

        Exactly! As I grok it, scanned statements are effectively ignored, except when they affect the compilation of other code. That's what a scanned statement is! For example, if you DIM lSomething AS LONG and then never use lSomething, it will have no effect whatsoever on the final EXE or DLL. Would you want it to? Should it trip a compile-time error?

        > Kinda shoots (...) the advantages of #DIM ALL, doesn't it?

        Not at all! You told the compiler to require you to DIM all of your variables, and it did exactly that. #DIM ALL has saved me from many, many, many problems. Saying that this "quirk" makes it worthless is... overly dramatic, in my opinion. {G}

        IMO, the paintbrush's job is to do exactly what the artist instructs it to do. I'm sure you will agree that it is up to the artist to become familiar with his tools, in order to make the best use of them. If we can't credit the paintbrush, we can't blame it either.

        Don't get me wrong... I would not mind at all if something like your #NAMECHECK ON was added to the compiler at some point in the future. Somewhere in the PowerBASIC suggestion box is an entry with my name on it, describing my wish for a $DIM STRICT option that would catch many different errors. After all, if you want the compiler to catch a local variable name that "conflicts" with a global one, why shouldn't it catch a global that is only used in one function and display and error message like "this is not a global variable, it is a static variable". And I wouldn't mind having the ability to detect those "declared but unused variables" like my lSomething example above, to keep my source code clean.

        But I've come to believe that those things -- and a long list of others -- belong in a source code proofreading program of some kind, not in the compiler itself. That's because I want a fast, efficient, two-pass compiler that does exactly what I tell it to. And if an external proofer can give me a third pass for "details" when I need it, great! My feeling is that we should let the developers at PowerBASIC concentrate on the compiler, and on the types of things that must be done in the compiler itself. There are probably a hundred different people who frequent this BBS every day who could write a very good source code proofreader! I'd rather have Bob Zale and the crew working on ActiveX/Linux/etc.

        Here's a suggestion, to help you live with the status quo... In the time since I've "moved" from DOS to Windows programming I have cultivated the habit of using "Hungarian notation" for all of my variable names. For example, glSomething would be a GLOBAL LONG variable, and ssSomething would be a STATIC STRING, and so on. Using my personal system, sSomething would be a LOCAL string... I do not usually use a prefix to denote a LOCAL scope. And every one of my DIM statements uses the 100% explicit DIM... AS GLOBAL LONG syntax. Some people turn up their nose at prefixes like that, but in my opinion they are more intuitive -- and certainly no more difficult to type -- than suffixes like $ and #.

        And after a while, seeing something like DIM gaQwerty AS LOCAL ASCIIZ will jump right out at you as an obvious error. Hungarian prefixes, properly done, make it impossible (with the exception of blatant errors, of course) to use the same variable name for a GLOBAL and for a LOCAL variable, because the scope is part of the variable name.

        -- Eric




        "Not my circus, not my monkeys."

        Comment


        • #5
          Michael,

          The GLOBAL isn't ignored. If you had another Sub or Function in your code where you DIDN'T also have a local variable with the same name, you would be able to interact with the global variable.

          Visual C/C++, Borland C/C++, and Delphi all allow the same type of variable scoping as PowerBASIC. It can be a *very* powerful feature if you use it correctly.

          I don't know specifically how PowerBASIC does it internally... But the way that most compilers support "locals" is to pre-append the name of the function (or Sub) in front of every local variable and label.

          So, to the compiler symbol table you would have two variables:

          QWERTY
          PBMAINQWERTY

          Every instance of a local scoped variable internally is references this way. That way, it's not possible for the compiler to accidentally use the same location in memory for variables.

          However, as I mentioned in my email to you, the C compilers and Delphi will *warn* you if you have a local variable with the same name as a global. It's strictly a warning, not an error, so it compiles anyway. PowerBASIC's not yet set up to provide warnings. It's on the wish list, though.

          --Dave

          Home of the BASIC Gurus
          www.basicguru.com

          Comment


          • #6
            I'd like to point out that the behaviour for arrays is different.
            You have to "GLOBAL TheArray() AS LONG" before your code, but can only "DIM TheArray(1000) AS LONG" inside a sub or function.
            The second one is referring to the GLOBAL array and NOT a LOCAL one.

            For the wish list:
            A compiler switch to switch on warnings about these, for debugging reasons only.

            Peter.

            [email protected]

            Comment


            • #7
              Peter, to help reduce the confusion when DIMming/REDIMming a global array, we recommend that you include the GLOBAL keyword in the statement: REDIM TheArray(1200) AS GLOBAL LONG

              Lance
              PowerBASIC Support
              Lance
              mailto:[email protected]

              Comment


              • #8
                Hay Guys you're missing the obvious here:
                Qwerty as an ASCIIz string and Qwerty as a LONG have ALWAYS been seperate variables in BASIC!
                eg: X$, X%, X&, X! are all individual variables.
                Right?
                C'ya
                Don

                http://www.ImagesBy.me

                Comment


                • #9
                  What might help to prevent inadvertent mishandling of variables
                  is to add a prefix to Global variable names which would distinguish
                  them from the Locals: GLOBAL g_Qwerty AS ASCIIZ * 80


                  Ron

                  Comment


                  • #10
                    While were on this subject, I'd like to suggest maybe a warning message or compile time error in trying to redim arrays contained in UDTs, after trying this weird things happened in the program and then a GPF.
                    After looking at the PB5 help file
                    The total size of a UDT must be known at compile time, therefore items like dynamic strings which very in size can not be part of the TYPE. A STRING PTR can..
                    I figured out why, after 2 days of head scratching.

                    Regards,

                    Kev

                    Comment


                    • #11
                      Thanks Eric! (it is over a year later) and I
                      found this jewel. I dimmed a string in a
                      subprogram that was already a global and it
                      correctly lost its value. It was definitely
                      a hard one to find. I'll prefix globals
                      with g_ as you suggested to avoid this.




                      ------------------
                      How long is an idea? Write it down.

                      Comment


                      • #12
                        Mike (Doty);

                        The use of Globals is always a precarious thing. They are the most
                        likely of variables to cause troubles. On the other hand Globals
                        are a very powerful tool !

                        The suggestion of using a Prefix for Globals is an 'absolute must" IMO.

                        Some prefixs are ovious, like h for a handle (ie. hWnd, hCtrl, hFont, hBmp).
                        They are very important for writing clean understandable code.

                        Now when it comes to Globals, they are the most likely to be abused
                        and can cause confusion.

                        I like to use a special prefix in front of "all" my Globals, like
                        App_.

                        examples:

                        Code:
                        GLOBAL APP_Something1&
                        GLOBAL APP_Something2$
                        GLOBAL APP_MainhWnd&
                        Now when I write a DLL, I use the prefix :

                        DLL_



                        ------------------
                        Chris Boss
                        Computer Workshop
                        Developer of "EZGUI"
                        http://cwsof.com
                        http://twitter.com/EZGUIProGuy

                        Comment

                        Working...
                        X