On Fri, 23 Feb 1996, Paul Duda wrote: > PowerMac 7100/66 System 7.5.1 > Macperl v5.0.6r1m > > Why does the following script only produce the expected results the first time > the script is run? > > for ($i = 0;$i < 5;$i++) { > vec($vector, $i, 1) = 1; > print $i, '. Setbits are: ', unpack("%32b*", $vector), "\n"; > } > print '$vector is: "', $vector, '" or ', unpack("b*", $vector), "\n"; > > Expected results and the actual results of the first run > -------------------------------------------------------- > 0. Setbits are: 1 > 1. Setbits are: 2 > 2. Setbits are: 3 > 3. Setbits are: 4 > 4. Setbits are: 5 > $vector is: "#031#" or 11111000 > > Results of subsequent runs without quitting and relaunching MacPerl > ------------------------------------------------------------------- > 0. Setbits are: 0 > 1. Setbits are: 48 > 2. Setbits are: 112 > 3. Setbits are: 0 > 4. Setbits are: 5 > $vector is: "#031#" or 11111000 > > A work around for this problem is to quit and relaunch MacPerl after running > a script that uses vec() and unpack(). Can I be sure that the results will > really be correct the first time the script is run? > > Has anyone else noticed this and thought it was a problem? The relevent code from pp.c is: ... static char* bitcount = 0; ... if (!bitcount) { Newz(601, bitcount, 256, char); for (bits = 1; bits < 256; bits++) { if (bits & 1) bitcount[bits]++; if (bits & 2) bitcount[bits]++; if (bits & 4) bitcount[bits]++; if (bits & 8) bitcount[bits]++; if (bits & 16) bitcount[bits]++; if (bits & 32) bitcount[bits]++; if (bits & 64) bitcount[bits]++; if (bits & 128) bitcount[bits]++; } ... This allocates a 256 byte array then sets it up with the corrects number of bits for each os the 256 possible values of a byte. The pointer is declared static, so it retains it's value (pointing to the array) on subsequent calls to the same routine. However, when a script ends, the CleanupPerl routine (in MPScript.c) calls: ... free_pool_memory('PERL'); ... which frees the memory allocated to the array. The pointer bitcount then becomes a stale pointer to unallocated memory which is written over when the next script runs. Ouch. One relatively easy way to fix this would be to declare bitcount as a static array with the values already defined, like this: static char bitcount[256] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 } ...which I just created with the following PERL script (look familiar?): for $i (0..255) { $bitcount = 0; if ($i & 1) { $bitcount++ } if ($i & 2) { $bitcount++ } if ($i & 4) { $bitcount++ } if ($i & 8) { $bitcount++ } if ($i & 16) { $bitcount++ } if ($i & 32) { $bitcount++ } if ($i & 64) { $bitcount++ } if ($i & 128) { $bitcount++ } unless ($i % 16) { print "\n " } print "$bitcount, "; } Of course, Matthias would have to incorporate this (or a different fix) into his code for you. John Peterson -- University Networking Services -- Brigham Young University Internet: John_Peterson@byu.edu Phone: (801) 378-5007