Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Another issue: Changing one variable instantly changes the value of another variable
#1
I have a short subroutine that takes a path and removes the quotes if the path is enclosed in quotes. It then removes any trailing backslash from the path if one exists.

I was getting some unexpected results, so into debug mode I went to find the problem. As I step through the code one line at a time, I find this problem:

As soon as I execute the line that reads Temp$ = "" not only does Temp$ get set to "" but in that very moment Path$ also gets set to "" (an empty string). For the life of me, I cannot make sense of why this happens.

A few notes:

1) Path$ is not defined outside of this subroutine, so it is local to the subroutine only.

2) Temp$ is DIMed at the start of my program as a SHARED string, so that variable should be available globally.

I apologize for not supplying the full code. The problem is that this is a part of a program almost 15,000 lines long now.

Can anyone give me anything to look for here? I simply cannot see how changing one variable would instantly change another variable as well.



Code: (Select All)
Sub CleanPath (Path$)

    ' Remove quotes and trailing backslash from a path

    ' To use this subroutine: Pass the path to this sub, the sub will return the path
    ' without quotes and a trailing backslash in Temp$.

    Dim x As Integer

    ' start by stripping the quotes

    Temp$ = ""

    For x = 1 To Len(Path$)
        If Mid$(Path$, x, 1) <> Chr$(34) Then
            Temp$ = Temp$ + Mid$(Path$, x, 1)
        End If
    Next x

    ' Remove the trailing backslash, if present

    If Right$(Temp$, 1) = "\" Then
        Temp$ = Left$(Temp$, (Len(Temp$) - 1))
    End If

End Sub
Reply
#2
Hmm, I gave it a try by making a simple program to call `ClearPath()`, but even with Temp$ as shared I can't get it to do what you're describing.

If you're able, it would help a lot is if you could zip up your `./internal/temp/` folder after compiling the program and attach it to a post. The particular file I'm interested in is `./internal/temp/main.txt` but some others may be relevant too. That file contains the produced C++ code, so if it's an issue with the code generation that would tell us. If you want to look yourself, it's a matter of finding `void SUB_CLEANPATH` in it and then viewing the behavior, but it's a bit hard to read if you don't know what you're looking at Smile
Reply
#3
I think that I solved this. I need to verify this back on my original system where I encountered to issue, but on my laptop I changed the variable named Path to Path1 and that seems to have solved the issue. Maybe Path is a reserved name that cannot be used as a variable name?
Reply
#4
First thing I'd try is to pass via a temp variable:

SUB CleanPath (tempPath$)
Path$ = tempPath$

The issue is probably from a call such as :

ClearPath temp$

With passing matching types with SUB/FUNCTION, we pass the offsets to the variable and not the value of the variable. If temp$ is passed, Path$ **IS** temp$.
Reply
#5
Uhmmm, unless temp$ is shared (which would be kinda odd) your sub doesn't do anything to the state of the program outside the sub???

It certainly doesn't change Path$, you would need a final line Path$ = Temp$.
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply
#6
Like Steve said, watch what you do with variables passed to FUNCTIONS AND SUBs. Because you do manipulate the original values within the routine. Which if your careful can be a big and powerful feature, if your not careful it can be a living nightmare.

In QB4.5 you could do this with FUNCTIONs alone, but in QB64 it happens in both.
Reply
#7
Steve, it seems that you were correct. Creating a temporary variable did the trick, although I would love to know where the problem was originating from.

For now, I'll take the win, but I may eventually try to figure out the source of the problem. It's not going to be easy because the flow of the code in this particular are calls a subroutine, which then in turn calls another subroutine, which then finally calls a third subroutine. Following the variables through all those levels may be a little tricky.

In any case, thanks for the idea. I've now modified several of my subroutines to put temp variables in place and hopefully avoid other similar situations.
Reply
#8
(06-17-2022, 03:12 AM)bplus Wrote: Uhmmm, unless temp$ is shared (which would be kinda odd) your sub doesn't do anything to the state of the program outside the sub???

It certainly doesn't change Path$, you would need a final line Path$ = Temp$.

As per opening post:  2) Temp$ is DIMed at the start of my program as a SHARED string, so that variable should be available globally.

So let's say there's a point in that program that looks like this:

ClearPath Temp$


Now the SUB uses Path$ as the variable name, but they'll share the same offset.  For all intents and purposes Path$ *IS* Temp$...  When Temp$ = "" a few lines into the sub, Path$ will = "" as well.  <-- This is the glitch we're seeing at work.

Now, with the issue diagnosed, I don't think finding it inside the program will be as simple as looking for a ClearPath Temp$.  From my personal experience, I'd imagine the issue to come from something like:

SUB SetSlashes (Link$)
 DO  UNTIL INSTR(Link$, "/") = 0
     MID$(Link$, INSTR(Link$, "/") = "\"
 LOOP
 ClearPath Link$
END SUB

At this point the program then does a SetSlashes Temp$, so Link$ = Temp$, which calls ClearPath which makes Path$ = Temp$, which leads to the roundabout issue of changing Temp$ changing Path$.

Best advice I can give to avoid this issue:
  **Unless you need a return value via your SUB or FUNCTION parameter, pass to a temp variable and only use it to assign to a different value for the sub's exclusive use.  **

Don't change your original variable, and you'll never have to worry about corruption of data that those changes might cause.  Wink
Reply
#9
(06-17-2022, 03:12 AM)bplus Wrote: Uhmmm, unless temp$ is shared (which would be kinda odd) your sub doesn't do anything to the state of the program outside the sub???

It certainly doesn't change Path$, you would need a final line Path$ = Temp$.

Dang you did DIM Shared Temp$, sorry I suck at reading!

IMHO this is how I would handle this function:
Code: (Select All)
' don't share temp$, temp$ is supposed to be temporary!!!
test$ = "C:\Dir1\Dir2\"
Print CleanPath$(test$)

Function CleanPath$ (Path$) ' this is clearly a Function in my opinion!

    ' Remove quotes and trailing backslash from a path

    ' To use this subroutine: Pass the path to this sub, the sub will return the path
    ' without quotes and a trailing backslash in Temp$.

    Dim x As Integer

    ' start by stripping the quotes

    Temp$ = ""

    For x = 1 To Len(Path$)
        If Mid$(Path$, x, 1) <> Chr$(34) Then
            Temp$ = Temp$ + Mid$(Path$, x, 1)
        End If
    Next x

    ' Remove the trailing backslash, if present

    If Right$(Temp$, 1) = "\" Then
        Temp$ = Left$(Temp$, (Len(Temp$) - 1))
    End If
    CleanPath$ = Temp$
End Function


How do you get double quotes in a path or filename? (Just really curious!)
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply
#10
(06-17-2022, 02:08 PM)bplus Wrote: IMHO this is how I would handle this function:
Code: (Select All)
' don't share temp$, temp$ is supposed to be temporary!!!
test$ = "C:\Dir1\Dir2\"
Print CleanPath$(test$)

Function CleanPath$ (Path$) ' this is clearly a Function in my opinion!

    ' Remove quotes and trailing backslash from a path

    ' To use this subroutine: Pass the path to this sub, the sub will return the path
    ' without quotes and a trailing backslash in Temp$.

    Dim x As Integer

    ' start by stripping the quotes

    Temp$ = ""

    For x = 1 To Len(Path$)
        If Mid$(Path$, x, 1) <> Chr$(34) Then
            Temp$ = Temp$ + Mid$(Path$, x, 1)
        End If
    Next x

    ' Remove the trailing backslash, if present

    If Right$(Temp$, 1) = "\" Then
        Temp$ = Left$(Temp$, (Len(Temp$) - 1))
    End If
    CleanPath$ = Temp$
End Function


How do you get double quotes in a path or filename? (Just really curious!)

You'd still end up with the same root issue though when you did a return$ = ClearPath(Temp$).   If I was going the way you're mentioning, I'd do it like so:


Code: (Select All)
Function CleanPath$ (Path$) ' this is clearly a Function in my opinion!


    STATIC Temp$ 'Make certain that Temp$ is local to the sub and we don't use the global variable by accident


    ' Remove quotes and trailing backslash from a path

    ' To use this subroutine: Pass the path to this sub, the sub will return the path
    ' without quotes and a trailing backslash in Temp$.

    Dim x As Integer

    ' start by stripping the quotes

    Temp$ = ""

    For x = 1 To Len(Path$)
        If Mid$(Path$, x, 1) <> Chr$(34) Then
            Temp$ = Temp$ + Mid$(Path$, x, 1)
        End If
    Next x

    ' Remove the trailing backslash, if present

    If Right$(Temp$, 1) = "\" Then
        Temp$ = Left$(Temp$, (Len(Temp$) - 1))
    End If
    CleanPath$ = Temp$
End Function

Notice that Temp$ is now a STATIC variable, forced to be localized to the Function itself, and thus can't ever be corrupted via the global variable named Temp$.  There's a reason why QBASIC offered STATIC and local variables, even if most people never bothered to use them.  Wink
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Linux Lubuntu INKEY$ issue TempodiBasic 7 648 09-09-2025, 02:53 PM
Last Post: hsiangch_ong
  Variable length type declarations dano 5 689 08-06-2025, 09:53 PM
Last Post: dano
  Determining if variable or static string is passed to a Sub dano 9 1,225 06-20-2025, 06:31 PM
Last Post: CookieOscar
  Most efficient way to build a big variable length string? mdijkens 9 1,893 01-17-2025, 11:36 PM
Last Post: ahenry3068
  Huge array of variable length strings mdijkens 9 1,833 10-17-2024, 02:01 PM
Last Post: mdijkens

Forum Jump:


Users browsing this thread: 1 Guest(s)