• Some users have recently had their accounts hijacked. It seems that the now defunct EVGA forums might have compromised your password there and seems many are using the same PW here. We would suggest you UPDATE YOUR PASSWORD and TURN ON 2FA for your account here to further secure it. None of the compromised accounts had 2FA turned on.
    Once you have enabled 2FA, your account will be updated soon to show a badge, letting other members know that you use 2FA to protect your account. This should be beneficial for everyone that uses FSFT.

Perl & multi-dimensional hashes

unhappy_mage

[H]ard|DCer of the Month - October 2005
Joined
Jun 29, 2004
Messages
11,455
I've got a chunk of code for configuring an ethernet adapter from a web-based interface, and one of the things it does is store the configuration of all the adapters on a machine before it goes changing configuration files. My code is like this:
Code:
$configuration = { };

foreach $adapter (@adapters)
 {
  %temphash = getconfig("$adapter");
  $configuration->{"$adapter"} = \%temphash;
 }
So it initializes a pointer to a hash, then for each adapter it gets configuration data (which is returned as a hash) and stores that one level down. To display this code, I do:
Code:
foreach $adapter (sort(keys %{$configuration}))
 {
  foreach $key (sort(keys %{$configuration->{"$adapter"}}))
   {
    print "Adapter $adapter: $key = ", $configuration->{"$adapter"}->{"$key"}, "<br>\n";
   }
 }
This, however, is the problem: This code generates the same data for eth0 and eth1, when they should be different. Here's the real output:
Code:
Adapter eth0: address = 192.168.1.15
Adapter eth0: broadcast = 192.168.1.255
Adapter eth0: gateway = 192.168.1.1
Adapter eth0: netmask = 255.255.255.0
Adapter eth0: network = 192.168.1.0
Adapter eth1: address = 192.168.1.15
Adapter eth1: broadcast = 192.168.1.255
Adapter eth1: gateway = 192.168.1.1
Adapter eth1: netmask = 255.255.255.0
Adapter eth1: network = 192.168.1.0
However, eth1 is on the 10 subnet, and all the other values should reflect this.

Any ideas?
 
Change

Code:
$configuration->{"$adapter"} = \%temphash;

to

Code:
%{$configuration->{"$adapter"}} = %temphash;

[edit] probably best with %{} enclosing everything.
 
Just a little background on why referencing can get you in trouble. When you reference a hash it just stores the location of the hash, not the hash itself. So when your script assigns new values to your temphash, whatever references it is also changed. So you assign a reference to temphash in your config hash, then change the values in temphash, so the referenced entry in config changes also. Referencing is good for saving space when passing objects around to functions, since you're not passing the actual object, just the location of it in memory. You function can then make changes to it, and when control is returned to the main program the object has been updated. Anyways, just my two cents.
 
Woh-pah! That does indeed work fine. I realized what the problem was, just not how to get around it; this makes much more sense now.

For extra credit, is there anything wrong with leaving out temphash altogether and just doing
Code:
       %{$configuration->{"$adapter"}} = getconfig("$adapter");
? It seems to work fine...
 
another solution would be to change
Code:
$configuration = { };

foreach $adapter (@adapters)
 {
  %temphash = getconfig("$adapter");
  $configuration->{"$adapter"} = \%temphash;
 }
to
Code:
$configuration = { };

foreach $adapter (@adapters)
 {
  my %temphash = getconfig("$adapter");
  $configuration->{"$adapter"} = \%temphash;
 }

or im pretty sure it should
 
Back
Top