bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

++ causes 2 variables to increment


From: phil colbourn
Subject: ++ causes 2 variables to increment
Date: Sun, 15 May 2016 21:42:11 +0100

Configuration Information [Automatically generated, do not change]:
Machine: i686
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='i686' -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='i686-pc-linux-gnu' -DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H   -I.  -I../. -I.././include -I.././lib  -D_FORTIFY_SOURCE=2 -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wall
uname output: Linux m41 4.2.0-34-generic #39-Ubuntu SMP Thu Mar 10 22:11:49 UTC 2016 i686 i686 i686 GNU/Linux
Machine Type: i686-pc-linux-gnu

Bash Version: 4.3
Patch Level: 42
Release Status: release

Description:

Odd behaviour when an undefined variable is used in arithemetic _expression_.

((++F[word]==M)) increments both F[word] AND M

But not always.

When M is null, M seems to be treated as 0 (as expected)
When M is assigned an integer value of an integer associative array element,
something goes wrong.

(just a guess, since as you will see, this is complex to demonstrate)

This can happen when M=1 but usually when M=2.


Repeat-By:

#!/bin/bash

p(){  # print variables
  printf "F[%s]=[%d]  M=[%d]  I=[%s]\n" "$1" $((F[$1]*1)) $((M*1)) "$I"
}

t(){  # iterate - part of a program that counts word frequency and tracks most frequent word
  p $W
  # M should not change here
  ((++F[$W]==M))&&I=  # pre-increment F[$W]. If equal to Max then I=NULL
  p $W
  # but sometimes, it does!
  ((F[$W]>M))&&M=F[$W]&&I=$W  # if F[$W]>Max then Max=F[$W]
  p $W
}

unset F
unset X
unset M
unset W
unset I

W="word"

echo setup

# it always fails, but at different iterations!

# why does it fail ever?????

# an example run

# run 3
#+ t
#+ p word
#+ printf 'F[%s]=[%d]  M=[%d]  I=[%s]\n' word 2 2 ''

# here, M=2

#F[word]=[2]  M=[2]  I=[]
#+ (( ++F[word]==M ))
#+ I=
#+ p word
#+ printf 'F[%s]=[%d]  M=[%d]  I=[%s]\n' word 3 3 ''

# without changing M, it is now 3!!!!!!

#F[word]=[3]  M=[3]  I=[]
#+ (( F[word]>M ))
#+ p word
#+ printf 'F[%s]=[%d]  M=[%d]  I=[%s]\n' word 3 3 ''
#F[word]=[3]  M=[3]  I=[]
#+ set +x

# only when setting M from F[$W] or F[word] causes it to fail at iteration 2

declare -iA F;                F[word]=1; M=F[word]           # fails run 2
#declare -iA F;                F[$W]=1;   M=F[$W]             # fails run 2

# all other ways to initialise M fail at iteration 3

#declare -iA F; declare -iA X; F[$W]=1;   X[dog]=1; M=X[dog]  # fails run 3
#declare -iA F; declare -iA X; F[$W]=1;   X[$W]=1;  M=X[$W]   # fails run 3
#declare -iA F;                F[$W]=1;   M=1                 # fails run 3
#declare -iA F;                F[$W]=1;   M="1"               # fails run 3
#declare -iA F;                F[$W]=1;   M=$((1*1))          # fails run 3
#declare -iA F;                F[$W]=1;   ((M=1))             # fails run 3
#declare -iA F;                F[$W]=1;   M=${F[$W]}          # fails run 3

I=$W

p $W

echo run 2
t

echo run 3
set -x
t
set +x

echo run 4
t


Fix:

declare -i M

This seems to 'fix' this.

Attachment: dead.bashbug
Description: Binary data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]