www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Note about Arrays as Assoc Array Keys

reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
I had a weird bug in my program, which I've now tracked down.  I thought 
I'd note it here on the newsgroup, for others who might encounter this.

I had an associative array where the key type was an array.  It turns 
out that the associative array stores the key by reference, not value. 
That is, if you use an array as a key, and then modify the array, then 
the key stored in the associative array will also change.  Look at this 
example code:

import std.stdio;
import std.string;
void main() {
   char[] key = "hello".dup;
   assoc_array[key] = "asdf";
   key[0] = 'x';
   foreach(char[] key,char *str; assoc_array)
     writef("%s %s\n", key,str[0..strlen(str)]);
}

It will print this:
xello asdf

In hindsight, this makes sense to mek - we don't want to copy things 
unnecessarily.  But the user should know that he needs to duplicate keys 
before using them to create new associative array entries:

   char[] key = <whatever>;
   assoc_array[key.dup] = <whatever>;
Oct 22 2004
next sibling parent "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:clbq2a$t8u$1 digitaldaemon.com...
 I had a weird bug in my program, which I've now tracked down.  I thought
 I'd note it here on the newsgroup, for others who might encounter this.

 I had an associative array where the key type was an array.  It turns
 out that the associative array stores the key by reference, not value.

Well D arrays are (mostly) reference types so it makes sense.
 That is, if you use an array as a key, and then modify the array, then
 the key stored in the associative array will also change.  Look at this
 example code:

 import std.stdio;
 import std.string;
 void main() {
    char[] key = "hello".dup;
    assoc_array[key] = "asdf";
    key[0] = 'x';
    foreach(char[] key,char *str; assoc_array)
      writef("%s %s\n", key,str[0..strlen(str)]);
 }

 It will print this:
 xello asdf

 In hindsight, this makes sense to mek - we don't want to copy things
 unnecessarily.  But the user should know that he needs to duplicate keys
 before using them to create new associative array entries:

    char[] key = <whatever>;
    assoc_array[key.dup] = <whatever>;

Oct 22 2004
prev sibling parent reply "Walter" <newshound digitalmars.com> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:clbq2a$t8u$1 digitaldaemon.com...
 In hindsight, this makes sense to mek - we don't want to copy things
 unnecessarily.  But the user should know that he needs to duplicate keys
 before using them to create new associative array entries:

    char[] key = <whatever>;
    assoc_array[key.dup] = <whatever>;

I would suggest instead following the COW (Copy On Write) technique instead. That means, that unless you are sure you own all references to a string, make a copy of it if you modify the contents of the string.
Oct 24 2004
parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Walter wrote:
 "Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
 news:clbq2a$t8u$1 digitaldaemon.com...
 
In hindsight, this makes sense to mek - we don't want to copy things
unnecessarily.  But the user should know that he needs to duplicate keys
before using them to create new associative array entries:

   char[] key = <whatever>;
   assoc_array[key.dup] = <whatever>;

I would suggest instead following the COW (Copy On Write) technique instead. That means, that unless you are sure you own all references to a string, make a copy of it if you modify the contents of the string.

You're probably right, in most cases. It didn't work in my case, because I was interop-ing with C and the array I was using as a key was actually a C string that I'd sliced into an array. I didn't clue in that the C code would be later modifying the contents of the buffer. So, I had to dup the key.
Oct 25 2004