Announcement

Collapse
No announcement yet.

asciiz ptr in union (PBDLL60)

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

  • asciiz ptr in union (PBDLL60)


    Hello,

    I just started to port my sources from PBDLL50 to PBDLL60
    and ran into the following bug (?): In PBDLL50, you may
    have asciiz pointers as members in a union. In PBDLL60,
    they don't seem to work correctly:

    If you run the following code snippet in the PBDLL60
    debugger, only the first three characters (plus trailing
    zero ?) of the string "powerbasic" will copied into the
    destination location, instead of the full string. If you
    run it in PBDLL50, it works just fine.


    ---------------------------------------
    #compile exe

    union uAdr
    anything as dword
    szPtr as asciiz ptr
    end union


    function pbmain()

    local szString as asciiz * 80
    local szPtr as asciiz ptr
    local u as uAdr

    szPtr = varptr(szString)
    u.anything = szPtr

    @szPtr = "powerbasic"
    #debug print szString ' writes "powerbasic" <--- correct

    [email protected] = "powerbasic"
    #debug print szString ' writes "pow" <--- wrong

    end function

    ---------------------------------------------


    Maybe I am using an "old" version of the compiler (07-01-99) ?

  • #2
    Peter --
    Try this

    #Compile Exe
    Union uAdr
    anything As Dword
    szPtr As Asciiz Ptr * 80
    End Union
    Function PbMain()
    Local szString As Asciiz * 80
    Local szPtr As Asciiz Ptr * 80
    Local u As uAdr
    szPtr = VarPtr(szString)
    u.anything = szPtr
    @szPtr = "powerbasic"
    MsgBox szString ' writes "powerbasic" <--- correct
    [email protected] = "powerbasic"
    MsgBox szString ' writes "powerbasic" also
    End Function

    PS. I have the same date of PB/DLL (downloaded at the beginning of December)
    About bug. It's not clear how compiler will process
    [email protected] = "powerbasic" if length of Asciiz string is not declared.
    (compiler should control length !)
    I think that for this assignment PB/DLL accepts 4, instesd of information about mistake.




    [This message has been edited by Semen Matusovski (edited January 13, 2000).]

    Comment


    • #3
      Interesting observation folks, I've sent a note about it to R&D. Thanks for letting us know, and well done to Semen for noting the workaround: simply give the ASCIIZ PTR a size of at least 1.

      Code:
      UNION uAdr
        anything AS DWORD
        szPtr AS ASCIIZ PTR [b]* 1[/b]
      END UNION

      -------------
      Lance
      PowerBASIC Support
      ( mailto:[email protected][email protected]</A> )
      Lance
      mailto:[email protected]

      Comment


      • #4
        Lance --
        About 1 - works only in this context. Pls, see how I corrected message.
        If to set 1 [email protected] simply is not executing.
        Compiler should not allow assignments for Asciiz Ptr, because a length is not defined.
        "Workaround" is to use Asciiz Ptr * CORRECT LENGTH

        Looks terrible following code
        #Register None
        #Compile Exe

        Function PbMain()
        Local szString As Asciiz * 5
        Local szPtr As Asciiz Ptr
        szPtr = VarPtr(szString)
        @szPtr = "powerbasic"
        MsgBox szString ' "powerbasic" !!! instead of powe
        ' potentional errors
        End Function

        Sometimes a variant Asciiz Ptr with undefined length could be useful.
        But it's necessary to include into .HLP a WARNING, something "compiler doesn't test length"


        [This message has been edited by Semen Matusovski (edited January 13, 2000).]

        Comment


        • #5
          You are now discussing pointers in a different light:

          In the case where you use the pointer:
          Code:
          Function PbMain()
            Local szString As Asciiz * 5
            Local szPtr As Asciiz Ptr ' a general asciiz pointer, no specific size!
            szPtr = VarPtr(szString)
            @szPtr = "powerbasic"
            MsgBox szString ' "powerbasic" !!! instead of "powe"
          You are intentionally creating a GPF because you are ignoring the size of the data storage area. In this case, 5 bytes (4 characters plus a NUL byte)... the solution is to either specify the size of the asciiz pointer when the pointer is DIMmed, or handle the string truncation yourself.

          This is different from the apparent bug that Peter's "asciiz pointer within a Union" appears to cause... setting the pointer length to 1 in Peter's code works fine. Obviously using the correct length is preferable. Happy now?


          -------------
          Lance
          PowerBASIC Support
          ( mailto:[email protected][email protected]</A> )
          Lance
          mailto:[email protected]

          Comment


          • #6
            I've only been programming in PB for about 2 months but this is what
            I understand pointer definitions to be in PB6.

            #COMPILE EXE

            UNION uAdr
            anything AS DWORD
            szPtr AS ASCIIZ PTR
            END UNION


            FUNCTION PBMAIN()

            LOCAL szString AS ASCIIZ * 80
            LOCAL szPtr AS ASCIIZ PTR
            LOCAL u AS uAdr

            szPtr = VARPTR(szString)
            u.anything = szPtr

            @szPtr = "powerbasic"
            #DEBUG PRINT szString ' writes "powerbasic" <--- correct

            u.szPtr = szPtr ' Assign pointer to a pointer in union
            #DEBUG PRINT [email protected] ' writes "powerbasic" <--- correct was wrong

            END FUNCTION

            This works just like it's supposed too. This union sure does look
            strange since I do not know how the code is used. Why not just a
            standard TYPE structure.

            Cecil

            Comment


            • #7
              Lance,

              I have reported to Bob a problem I found with assigning a value to a ASCIIZ PTR in a structure. I have no problem getting the data but when I try to do an assignment, it only copies 31 bytes then adds a CHR$(0). The rest of the string never gets updated with my changes.

              I'm doing this inside an exported function (DLL) using the structure being passed an argument.

              I got arround the problem using PEEK$ / POKE$ by changing the element in the structure to DWORD from a ASCZII PTR type.

              John

              P.S.

              Dave has the code I'm using that shows the problem.

              [This message has been edited by John Spikowski (edited January 14, 2000).]

              Comment


              • #8
                John, I've not seen your problem report.

                Cecil, you certainly have a good understanding of pointers.
                The original code (posted by Peter) exploits the way a UNION operates - by assigned the target address to the DWORD member of the UNION the pointer should automatically receive a valid address, however, because the target string is unexpectedly truncated when accessed with the pointer, there seems to be a problem.

                Your code does not have this problem (apparently) because you have explicitly assigned a target address to the pointer in the union.

                As noted, I've referred this matter to R&D, and I'll post any relevant information I receive back.

                -------------
                Lance
                PowerBASIC Support
                ( mailto:[email protected][email protected]</A> )
                Lance
                mailto:[email protected]

                Comment


                • #9
                  Hey guys, who's pulling who's leg here. I just compiled the same code
                  under PB5 and got the same prob. Code changed as follows:

                  $COMPILE EXE

                  UNION uAdr
                  anything AS DWORD
                  lpszPtr AS ASCIIZ PTR
                  END UNION


                  FUNCTION PBMAIN()

                  LOCAL szString AS ASCIIZ * 80
                  LOCAL szPtr AS ASCIIZ PTR
                  LOCAL u AS uAdr

                  szPtr = VARPTR(szString)
                  u.anything = szPtr

                  @szPtr = "powerbasic"
                  $DEBUG PRINT szString ' writes "powerbasic" <--- correct

                  [email protected] = "powerbasic"
                  $DEBUG PRINT szString ' writes "pow" <--- wrong obviously

                  END FUNCTION

                  Was my PB5 compiler out of date? Never used PB5, went straight
                  to PB6.

                  Comment


                  • #10
                    Guys --
                    I imagine, how compiler works, and a situation becomes clear.
                    For Union compiler calculates a size (maximum from all elements) and this is a restriction for [email protected]
                    Take initial variant and after

                    Union uAdr
                    anything As Dword
                    szPtr As Asciiz Ptr

                    insert additional line

                    mama As String * 6

                    You will receive "power", because compile thinks that a length of Union is 6 (szPtr As Asciiz Ptr = szPtr As Asciiz Ptr * 6)

                    Change to mama As String * 11. It will be "powerbasic".

                    Comment


                    • #11
                      From the examples it's pretty clear that what we have here is a bug in the compiler: it accepts ASCIIZ PTR as a member without demanding a length.

                      MCM


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

                      Comment


                      • #12
                        Hi Matthias

                        From the examples it's pretty clear that what we have here is a bug in the compiler: it accepts ASCIIZ PTR as a member without demanding a length
                        It does look like a bug although I don't think that the bug lies with accepting an ASCIIZ PTR as a member without requiring a length. By definition a pointer points to another structure whose length is already defined - IMO requiring a pointer to state how long the original string is defeats the object.

                        Cheers

                        Florent

                        Comment


                        • #13
                          Quote "By definition a pointer points to another structure whose length is already defined"
                          During compiling PTR refers to nothing and a length of original string is unknown.

                          Comment


                          • #14
                            Hi Semen

                            I don't agree - pointers are often used with dynamically allocated memory as an alternative to pointing to a pre-declared ASCIIZ string. If the compiler requested that an ASCIIZ PTR have a pre-declared length such code as the example below would be illegal which IMHO would weaken the usefulness of ASCIIZ pointers:

                            Code:
                            #COMPILE EXE
                            
                            DECLARE FUNCTION SysAllocString  _
                            LIB "OLEAUT32.DLL" ALIAS "SysAllocString" ( _
                                   szOleChar AS ASCIIZ _
                                   ) AS DWORD
                            DECLARE SUB SysFreeString _
                            LIB "OLEAUT32.DLL" ALIAS "SysFreeString" ( _
                                  BYVAL sBstr AS DWORD)
                            
                            
                            TYPE EXAMPLE_STRUC0
                                lKey AS LONG
                                lRec AS LONG
                            END TYPE
                            
                            TYPE EXAMPLE_STRUC
                                szKey AS ASCIIZ PTR
                                szRec AS ASCIIZ PTR
                            END TYPE
                            
                            UNION EXSTRUC
                                Ex0 AS EXAMPLE_STRUC0
                                Ex1 AS EXAMPLE_STRUC
                            END UNION
                            
                            FUNCTION PBMAIN() AS LONG
                                DIM tExStruc AS EXSTRUC
                             
                                tExStruc.Ex1.szKey = SysAllocString("MYKEY")
                                tExStruc.Ex1.szRec = SysAllocString("MYREC")
                             
                                MSGBOX "Key " + [email protected] + CHR$(13) + _
                                       "Record " + [email protected]
                             
                                MSGBOX "Key long" + STR$(tExStruc.Ex0.lKey) + CHR$(13) + _
                                       "Record long" + str$(tExStruc.Ex0.lRec)   
                             
                                CALL SysFreeString(tExStruc.Ex1.szKey)
                                CALL SysFreeString(tExStruc.Ex1.szRec)
                             
                            END FUNCTION
                            This is a trivial example, I know, but it hopefully shows what I'm talking about: an ASCIIZ PTR by definition points to a predefined ASCIIZ string with a predeclared length OR to dynamically allocated memory.

                            Cheers

                            Florent



                            [This message has been edited by Florent Heyworth (edited January 14, 2000).]

                            Comment


                            • #15
                              ASCIIZ PTR without a length is perfectly valid. The length is determined by the terminating nul.

                              This is a likely parsing bug in the compiler and as Lance has already stated, it has already been reported to the R&D team.

                              As soon as we get work from R&D, we'll post a note.

                              --Dave


                              -------------
                              PowerBASIC Support
                              mailto:[email protected][email protected]</A>

                              Home of the BASIC Gurus
                              www.basicguru.com

                              Comment


                              • #16
                                Hi Florent,

                                I think you just hit the nail on the head. I'm totally in agreement
                                with what you had to say about "pointers". As I stated earlier, the
                                above code in PB5 produced the same result.

                                Here's MHO as to what is going on in the original code:

                                1. The elements of an union occupy the same memory space, ie 4 bytes
                                (32 bits) DWORD and ASCIIZ PTR.

                                2. Assigning u.anything to szPtr does not constitute that szPtr in the
                                union will be the same. We're talking about a string here.

                                3. Since the pointer in the union can only handle a 4 byte length, the
                                string gets truncated to 4 bytes, "pow" + $NUL. String was never
                                assigned a length as far as union pointer was concerned.

                                That's why I assigned the pointer in the union explicitly to the program
                                pointer szPtr. While the fix that Lance proposed will work, I don't believe
                                that is what pointers were actually designed to do.

                                I don't think that this a PB compiler bug. If you force the compiler to
                                do a length assignment requirement, then the TYPE structures in Win32API.INC
                                are going to be in for a pleasant surprise, ie WndClass and so on.

                                Cheers,
                                Cecil

                                Comment


                                • #17
                                  Hi Cecil

                                  [Just corrected my mail]
                                  I agreed with you at first but on 2nd scrutiny you are incorrect (IMO) in your analysis. This is most likely a parsing problem in the compiler as Dave and Lance mentioned. Assigning szPtr to u.anything should assign the address of szString to szPtr.

                                  Your analysis, however, describes very accurately, again IMO, what the compiler is actually doing. My version of PBDLL 5.0 however produces the same result as the PBDLL6.0 compiler


                                  Cheers

                                  Florent



                                  [This message has been edited by Florent Heyworth (edited January 14, 2000).]

                                  Comment

                                  Working...
                                  X