www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - AA of AAs -- ArrayBoundsError

reply nobody <nobody mailinator.com> writes:
The following code results in an ArrayBoundsError with my v1.015 
compiler:

   typedef size_t IA;
   typedef size_t IB;
   typedef uint V;

   void main(char[][] args)
   {
     V[IB] [IA] test;
     test[cast(IA) test.length]
       [cast(IB) test[cast(IA) test.length].length] =
     cast(V) (test.length * test[cast(IA) test.length].length);
   }
Oct 29 2007
parent reply Matti Niemenmaa <see_signature for.real.address> writes:
nobody wrote:
 The following code results in an ArrayBoundsError with my v1.015 compiler:
 
   typedef size_t IA;
   typedef size_t IB;
   typedef uint V;
 
   void main(char[][] args)
   {
     V[IB] [IA] test;
     test[cast(IA) test.length]
       [cast(IB) test[cast(IA) test.length].length] =
     cast(V) (test.length * test[cast(IA) test.length].length);
   }

The problem is on the right hand side of the assignment, namely on the access test[cast(IA) test.length]. The AA test is empty, so retrieving any element will fail with an ArrayBoundsError. Assign test[1][1] = something; first, and then it will work. (1, because test.length will be 1 after the assignment.) -- E-mail address: matti.niemenmaa+news, domain is iki (DOT) fi
Oct 29 2007
parent reply nobody <nobody mailinator.com> writes:
Matti Niemenmaa wrote:
 nobody wrote:
 The following code results in an ArrayBoundsError with my v1.015 compiler:

   typedef size_t IA;
   typedef size_t IB;
   typedef uint V;

   void main(char[][] args)
   {
     V[IB] [IA] test;
     test[cast(IA) test.length]
       [cast(IB) test[cast(IA) test.length].length] =
     cast(V) (test.length * test[cast(IA) test.length].length);
   }

The problem is on the right hand side of the assignment, namely on the access test[cast(IA) test.length]. The AA test is empty, so retrieving any element will fail with an ArrayBoundsError. Assign test[1][1] = something; first, and then it will work. (1, because test.length will be 1 after the assignment.)

I really messed up the example. You are correct that my example should not work. However, both the following add functions fail when I think they shouldn't: import std.stdio; typedef size_t I; struct Si { uint val; } struct Sa { Si[I][I] table; void add(I i, Si si) { table[i][cast(I) table[i].length] = si; } } struct Sb { Si[][I] table; void add(I i, Si si) { if(table[i] is null) table[i] = new Si[0]; table[i].length = table[i].length + 1; table[i][table[i].length - 1] = si; } } void main(char[][] args) { Si si; Sa sa; try { sa.add(cast(I) 17, si); } catch(Error e) { writef("Sa failed\n"); } Sb sb; try { sb.add(cast(I) 17, si); } catch(Error e) { writef("Sb failed\n"); } } ---------------------------------------------------------------- Sa failed SB failed
Oct 29 2007
parent Matti Niemenmaa <see_signature for.real.address> writes:
nobody wrote:
 Matti Niemenmaa wrote:
 nobody wrote:
 The following code results in an ArrayBoundsError with my v1.015
 compiler:

   typedef size_t IA;
   typedef size_t IB;
   typedef uint V;

   void main(char[][] args)
   {
     V[IB] [IA] test;
     test[cast(IA) test.length]
       [cast(IB) test[cast(IA) test.length].length] =
     cast(V) (test.length * test[cast(IA) test.length].length);
   }

The problem is on the right hand side of the assignment, namely on the access test[cast(IA) test.length]. The AA test is empty, so retrieving any element will fail with an ArrayBoundsError. Assign test[1][1] = something; first, and then it will work. (1, because test.length will be 1 after the assignment.)

I really messed up the example. You are correct that my example should not work. However, both the following add functions fail when I think they shouldn't: import std.stdio; typedef size_t I; struct Si { uint val; } struct Sa { Si[I][I] table; void add(I i, Si si) { table[i][cast(I) table[i].length] = si; } }

This is essentially the same case as your original example. table[i].length results in an error because table[i] does not exist yet.
   struct Sb
   {
     Si[][I] table;
 
     void add(I i, Si si)
     {
       if(table[i] is null)
         table[i] = new Si[0];
 
       table[i].length = table[i].length + 1;
       table[i][table[i].length - 1] = si;
 
     }
   }

As above, "if (table[i] is null)" results in an error because table[i] does not exist yet. What would, however, work is "if (!(i in table))". (You might have noticed this if you would have output the error instead of just "Sb failed": the ArrayBoundsError is on the line where the if statement is.) BTW, you should post these on the digitalmars.D.learn newsgroup unless you're 100% sure they're bugs. -- E-mail address: matti.niemenmaa+news, domain is iki (DOT) fi
Oct 29 2007