perltux has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I have come across a very weird problem while trying to use Tk::ProgressBar.
Basically when running the following code, the output of the Label() after creating the ProgressBar seems to contain random bytes of the source code of the script itself rather than the value of the variable.

here is the example script:

#!/usr/bin/perl use strict; use warnings; use Tk; use Tk::ProgressBar; my %pid=(ex1=>{as=>'temp', val=>'-21.5'}); my $mw=MainWindow->new(); my $tmpbar=$mw->Frame()->pack( -padx=>30 ); PBar( \$tmpbar, \$pid{ex1}{val}, '-30', '70' )->pack(); $tmpbar->Label( -textvariable => \$pid{ex1}{val} )->pack(); $tmpbar->Label( -text => "$pid{ex1}{as}" )->pack(); print STDOUT "val Labels: $pid{ex1}{val}\n"; MainLoop; sub PBar { my($frame, $val, $min, $max)=@_; print STDOUT "val PBar1: $$val\n"; my $pbar=$$frame->ProgressBar( -anchor=>'s', -width=>40, -length=>500, -blocks=>100, -gap=>1, -resolution=>0.5, -variable=>$val, -from=>$min, -to=>$max ); print STDOUT "val PBar2: $$val\n"; return $pbar; }
when running this script you will see that the Label under the vertical ProgressBar instead of containing the value of $pid{ex1}{val}, prints out three random bytes that appear to be from the source of the script itself.

What is happening here? Memory corruption? ::confused::

Also (this is my second question), why does ProgressBar modify the value of $pid{ex1}{val} rather than just reading it?

Replies are listed 'Best First'.
Re: weird case of memory corruption?
by choroba (Archbishop) on May 12, 2021 at 07:00 UTC
    I can confirm the weird behaviour.

    See Re: TK::ProgressBar Color update which basically says "Don't use ProgressBar, it's buggy." and shows an alternative using Tk::Canvas.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
      bravo choroba!

      I simplified the OP example to trap (but only sometimes!!) the bagged behaviour

      #!/usr/bin/perl use Data::Dump; #https://www.perlmonks.org/index.pl?node_id=11132441 use strict; use warnings; use Tk; use Tk::ProgressBar; my %pid=(ex1=>{as=>'temp', val=> -21.5}); my $mw=MainWindow->new(); my $tmpbar=$mw->Frame()->pack( -padx=>30 ); my $pbar = $tmpbar->ProgressBar( -anchor=>'s', -width=>100, -length=>500, -blocks=>100, -gap=>1, -resolution=>0.5, -variable=>\$pid{ex1}{val}, -from=>-30, -to=>70, )->pack(); my $repeat; $repeat = $mw->repeat(500,sub{ $repeat->cancel() if $pid{ex1}{val} > += 65; unless ( defined $pid{ex1}{val} ){ print "WARNING: \$pid{ex1}{val} NO +T FOUND!!\n"; dd %pid; } $pid{ex1}{val}+=5; }); $tmpbar->Label( -textvariable => \$pid{ex1}{val} )->pack(); MainLoop;

      L*

      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
        I ran this code on v5.24 with good looking GUI, but with run time error:
        Use of uninitialized value in numeric ge (>=) at C:\Users\xxxx\Documen +ts\PerlProjects\Monks\node_id=11132441.pl line 31. WARNING: $pid{ex1}{val} NOT FOUND!! ("ex1", { as => "temp", val => undef })
        I am a bit perplexed.

        Update: I changed:

        $repeat->cancel() if $pid{ex1}{val} >= 65; # to the following... $repeat->cancel() if ($pid{ex1}{val} >= 65); and that seems to work better.
      That's a bummer. Thing is I have actually used Tk:ProgressBar previously with no issues, that's why I don't understand why it's misbehaving in this instance, I'm using it the same way as previously.

      Do you think that I should bring this to the attention of the maintainer, Slaven Rezić?
        Creating a bug report is always good. But check first the same issue hasn't been reported already.

        Also, as a workaround, you can set the value after creating the progress bar, e.g.

        my $value = $$val; my $pbar = $$frame->ProgressBar( ... ); $$val = $value;

        map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: weird case of memory corruption? -- Tk -textvariable
by Discipulus (Abbot) on May 12, 2021 at 06:56 UTC
    Hello perltux,

    ..really weird :) Firstly I removed all stringified numbers, all STDOUT explicit mention and implicit hash element access.. not the cause of your errors but just to clean the field.

    Then I suspect the problem being in the -textvariable behaviour: I suspect problem accessing elements of a nested datastructure. Infact uncommenting my DUMMY assignement I found sometimes val being undef (using dd to dump the whole hash)

    #!/usr/bin/perl use Data::Dump; use strict; use warnings; use Tk; use Tk::ProgressBar; my %pid=(ex1=>{as=>'temp', val=> -21.5}); my $mw=MainWindow->new(); my $tmpbar=$mw->Frame()->pack( -padx=>30 ); my $dummy = 'DUMMY'; # my $dummy = $pid{ex1}->{val}; PBar( $tmpbar, \$dummy, -30, 70 )->pack(); # PBar( $tmpbar, \$pid{ex1}->{val}, -30, 70 )->pack(); $tmpbar->Label( -textvariable => \$pid{ex1}{val} )->pack(); $tmpbar->Label( -text => $pid{ex1}->{as} )->pack(); print "val Labels: $pid{ex1}->{val}\n"; dd %pid; MainLoop; sub PBar { my($frame, $val, $min, $max)=@_; print "val PBar1: $$val\n"; my $pbar=$frame->ProgressBar( -anchor=>'s', -width=>100, -length=>500, -blocks=>100, -gap=>1, -resolution=>0.5, -variable=>$val, -from=>$min, -to=>$max ); print "val PBar2: $$val\n"; dd %pid; return $pbar; }

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
      I have never had problems with -textvariable in Labels using nested data structures despite using them frequently, this case is the first, so I think ProgressBar is somehow messing with it (you can see that ProgressBar actually resets the value of $pid{ex1}{val} to the '-from' value despite this not being a documented behaviour).

      If you try removing the ProgressBar the behaviour of the -textvariable in the Label will be consistently as expected.
        Hello again,

        you are rigth about -textvariable pointing to a nested val: it works correctly (see also why won't Tk textvariable take a reference to an array element? Tk::Entry not updating when textvariable changes. and perl/Tk Entry widget displays wrong value when -textvariable is shared).

        My dumping using Data::Dump dd method shows, if you uncomment and so use your original code PBar( $tmpbar, \$pid{ex1}->{val}, -30, 70 )->pack(); that sometimes val is undef:

        >perl tkprogressbar.pl val PBar1: -21.5 val PBar2: -30 ("ex1", { as => "temp", val => -30 }) val Labels: -30 ("ex1", { as => "temp", val => -30 }) >perl tkprogressbar.pl val PBar1: -21.5 Use of uninitialized value in concatenation (.) or string at tkprogres +sbar.pl line 39. val PBar2: ("ex1", { as => "temp", val => undef }) Use of uninitialized value in concatenation (.) or string at tkprogres +sbar.pl line 21. val Labels: ("ex1", { as => "temp", val => undef })

        L*

        There are no rules, there are no thumbs..
        Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: weird case of memory corruption?
by perltux (Monk) on May 12, 2021 at 13:57 UTC
    I believe the actual bug must be in Tk::Trace which is used by Tk::ProgressBar.
    I looked at the source code of Tk::ProgressBar itself but as far as I can tell there is nothing that could cause this memory corruption.

    The problem seems to be triggered by the fact that the same variable is traced both from a -textvariable in a Label and from Tk::ProgressBar.

      If I understand correctly, Tk::Trace works by tying the scalar using Tie::Watch. Could the problem be a result of "stacking" Tie::Watch on the same value?