Announcement

Collapse
No announcement yet.

Compiler Declares Error But Logic Flow Okay?

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

  • Compiler Declares Error But Logic Flow Okay?

    This code compiles with an error, saying that MyArray is not dimensioned (the offending line is commented).

    But as the program would execute, a Dim would be applied to MyArray before the offending statement would be seen - via the MyOtherSub which has MyArray passed to it for DIM'ing.

    Shouldn't this compile without error?

    Since the array is DIM'd under another name (a ByRef argument), I assume the compiler simply doesn't catch what's happening and gives the error. But I would have guessed that since the program logic allows DIMing before the offending line is reached, that the compiler would not have stated an error is present.

    I guess I haven't tried this "hidden" DIMing of an array before, to have seen the error the compiler gives.

    Is this consistent with what others have seen?

    As a workaround, I can DIM the array explicitly and use REDIM in MyOtherSub.

    Code:
    #Compile Exe
    #Dim All
    Global MyArray() As String
    Function PBMain () As Long
        MySub
        ? "done"
    End Function
    
    Sub MySub()
        MyOtherSub(MyArray())
        MyArray(5) = "test"          'this line gives the errror
    End Sub
    
    Sub MyOtherSub(TheArray() As String)
        Dim TheArray(25)
    End Sub
    BTW - in my bigger app, the MyOtherSub may be used to DIM any one of several different arrays (along with taking action on the array content) - hence the use of a Sub argument instead of explicitly DIMing the array by its original name.

  • #2
    There was recently a rather long discussion about this very thing but I can't remember which forum or thread. It was suggested that the compiler not check to see if an array has been dimensioned or not. However, I think at the end we came to the conclusion that the compiler needs to know how the array gets dimensioned so that it can determine proper addresses put in the executable. The address for MyArray(5) is going to be different than the address for MyArray(2,5) and if the compiler doesn't know if MyArray has one or two dimensions, it can't calculate the address.

    There are so many ways that the array could be dimensioned that the compiler either has no way of knowing or, at the very least, would take a lot of code to trace through your program execution, that it is much easier just to dimension the array as soon as possible after declaring it. In the case of global arrays, put the DIM at the start of PBMAIN. You can always use REDIM if you need to change the bounds later if you don't know what they are going to be when the program starts.
    Jeff Blakeney

    Comment


    • #3
      The compiler knows best. In effect you are trying to pass an array that has no descriptor table allocated for it ... yet. That being the case it can pass nothing, because the array has no allocated memory ...yet either . IOW there is nada to pass.

      Actually ... your code could show this this way. simplified.
      Code:
      #COMPILE EXE
      #DIM ALL
      
      GLOBAL GBArray() AS STRING
      
      FUNCTION PBMAIN () AS LONG
          ? ARRAYATTR(TheArray(),0)
          MySub(GBArray())
      END FUNCTION
      
      SUB MySub(TheArray() AS STRING)
          ? ARRAYATTR(TheArray(),0)
          WAITKEY$
      END SUB
      Last edited by Richard Angell; 25 Oct 2009, 11:37 AM.
      Rick Angell

      Comment


      • #4
        Thanks Jeff/Rick,

        I don't recall that thread, but am glad to see that it was discussed. I'll try to run it down.

        Otherwise, I'll just go ahead and use DIM in PBMain, with REDIM as required in subsequent code. I tried that approach in the sample code and it works just fine.

        Comment


        • #5
          There was recently a rather long discussion .... However, I think at the end we came to the conclusion that the compiler needs to know how the array gets dimensioned so that it can determine proper addresses put in the executable.
          Hmm, I recall the conclusion being the compiler does NOT need know the array has been DIM'd/REDIM'd, but was being condescending and maternal ("Microsoft-like") about it....

          Think about it... if the ARRAYATTR() function can query "has this array been dimensioned?" then the runtime can, too, and can simply ignore/error out any array functions called if the array has not been dimensioned.

          Then again, knowing how certain people feel about 'speed at all costs', it's possible the compiler was designed to assume by the time any array access is requested, that array HAS BEEN dimensioned, in which case the only way to do that is to take certain steps at compile time.

          With regard to finding an element of an undimensioned array in this line.....
          Code:
          MyArray(5) = "test"          'this line gives the errror
          .. I would think the declaration...
          Code:
          Global MyArray() As String
          ...which precedes this line would be sufficient to allow the compiler to 'find' element five, or generate ERROR 9 if it discovers at runtime there is no element five.


          In any event, just add ...
          Code:
            REDIM MyArray(0)
          ... in WinMain as the first thing, change to REDIM() in the myOtherSub procedure and everything will work out just ducky.

          MCM
          Last edited by Michael Mattias; 25 Oct 2009, 11:42 AM.
          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #6
            Michael, it is true we were leaning toward getting the compiler to not check to see if an array has been dimensioned but then Tom Hanlin popped in and said that he'd keep the request in mind but thought there might be a reason that the compiler needs to know if an array has been dimensioned. That's when it clicked in my mind that the compiler does need to know how an array gets dimensioned so it can figure out where each element is being stored. I thought I had posted a message to this effect in that thread but maybe I forgot to do it. I really need to find that thread again and check.

            If the compiler were to allow Gary's code to compile and we change the DIM in MyOtherSub to DIM TheArray(5, 25) then the line that says MyArray(5) = "test" should be invalid but the compiler wouldn't know that so it would have calculated an address for that array index assuming we are dealing with a single dimension array and put the data in the wrong spot in our two dimension array.

            It is possible for the compiler to be written to trace code and watch addresses to see if anything is referring to an array that has been declared but it would take a lot of extra code and I'm not sure I'd want to come up with an algorithm to deal with it. Even if that were done, there is no way for the compiler to know (unless it asked the user when compiling) if an array passed to a procedure in a DLL or other already compiled code gets dimensioned by that executable. It is far easier to make it a requirement that the array be dimensioned before it is used.
            Jeff Blakeney

            Comment


            • #7
              Found the other thread it is Pass Undimensioned Array As Parameter in the Programming forum.

              Turns out I didn't post the reply I thought I did so I just posted it.
              Jeff Blakeney

              Comment


              • #8
                It may well be as suggested above... it's doable (it has to be doable, because if you use a variable for a subscript, the compiler will generate ERROR 9 if "subscript var" happens to currently be 'out of range' when the call is made).... but the runtime requirement was deemed 'not worth' its cost if the only benefit were the ability support compile-time references to an un-DIMd/REDIMd array via an inline numeric literal subscript.

                Then again, I rarely use inline literals for subscripts. Actually I rarely use inline literals for anything.

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

                Comment


                • #9
                  Hmmm... just realized I posted in the Console, rather than PBWin forum. But I assume the discussion still holds.

                  Comment


                  • #10
                    just realized I posted in the Console, rather than PBWin forum. But I assume the discussion still holds.
                    A couple of weeks ago I looked thru both the PB/Win and PB/CC help files to see if I could find documentation, "arrays created by PB/CC and PB/Windows are identical and may be free passed as parameters or otherwise shared by procedures created by both compilers."

                    I failed to find such a statement.

                    However, it has always worked this way.
                    Michael Mattias
                    Tal Systems (retired)
                    Port Washington WI USA
                    [email protected]
                    http://www.talsystems.com

                    Comment


                    • #11
                      Originally posted by Michael Mattias View Post
                      It may well be as suggested above... it's doable (it has to be doable, because if you use a variable for a subscript, the compiler will generate ERROR 9 if "subscript var" happens to currently be 'out of range' when the call is made)
                      ERROR 9 is a run time error, not a compile time error. According to the documentation, all errors from 1 to 255 are run time errors (0 means no error) and the compiler will never return an error in this range. The compiler can, with #DEBUG ERROR ON, add code to your executable to return this error when your code is running. The compiler has no way to guarantee whether the value you specify for a subscript is within range or not unless you are using literals.

                      I suppose if the compiler were to interpret your code then it would know what the variable values are but then you'd be running the program before you even compiled it.
                      Jeff Blakeney

                      Comment


                      • #12
                        > ERROR 9 is a run time error, not a compile time error

                        Exactly. Meaning, the compiler-generated code CAN (or at least COULD) detect "oops array not dimensioned" or "Oops, no such subscript available now" at runtime, meaning it would not need to do so at compile time.

                        Q.E.D.

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

                        Comment

                        Working...
                        X