[Date Prev][Date Next][Thread Prev][Thread Next]
[Search]
[Date Index]
[Thread Index]
Re: [MacPerl] vec() & unpack() 5.0.6r1m
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