www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 1914] New: Array initialisation from const array yeilds memory trample

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1914

           Summary: Array initialisation from const array yeilds memory
                    trample
           Product: D
           Version: 1.028
          Platform: All
        OS/Version: Linux
            Status: NEW
          Severity: major
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla digitalmars.com
        ReportedBy: jason spashett.com


This bug is reproducible on (at least) Linux, DMD 1.028. Windows DMD 1.026

The following code prints "0", Unless I am mistaken "a" should be initialized
with the contents of const array i. y is corrupted. With this construct,
permissible or not, the compiler should not allow this to happen.

Note that direct initialization with an array (not though an intermediate
const) does work as expected.


import std.stdio;

struct S1
{
    const float[10] i = [0,0,0,0,0,0,0,0,0,0];
    float a[10] = i;
    int y=5;
}


void main()
{
    S1    s;
    writefln(s.y);
}


-- 
Mar 12 2008
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1914






This works correctly with gdc on linux, using dmd frontend 1.021. 

user vm-fruitbat:~$ gdc --version
gdc (GCC) 4.1.3 20070831 (prerelease gdc 0.25, using dmd 1.021) (Ubuntu
0.25-4.1.2-16ubuntu1)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

user vm-fruitbat:~$ gdc array_test.d
user vm-fruitbat:~$ ./a.out
5


-- 
Mar 13 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1914


jason spashett.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jason spashett.com





From looking at the assembly briefly, it appears that:

Direct initialisation is fine:

float a[10] = [0,0,0,0,0,0,0,0,0,0];

(compiler appears to generate "template" struct to initalise array and
following int in one go with rep movsd.

esi points to a correct "template" in this case.


In the case of 

...
const float[10] i = [0,0,0,0,0,0,0,0,0,0];
float a[10] = i;
...

Code is the same, but the "template" is wrong. Presumably because the compiler
does not understand the const array initialiser properly. 


-- 
Mar 13 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1914


jason spashett.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         OS/Version|Linux                       |All
            Version|1.028                       |1.030





Still present in DMD 1.030 on windows and on DMD 1.030 Linux.


-- 
Jun 06 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1914


smjg iname.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |smjg iname.com
           Keywords|                            |wrong-code





It seems that it's simply failing to initialise y correctly.  Changing main to

void main()
{
    S1    s;
    writefln(s.y);
    writefln(s.a);

    s.y = 4;
    writefln(s.y);
    writefln(s.a);
}

gives the output

0
[0,1,2,3,4,5,6,7,8,9]
4
[0,1,2,3,4,5,6,7,8,9]


-- 
Nov 20 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1914







 It seems that it's simply failing to initialise y correctly.  Changing main to
When I looked at the assembly, I think (can't remember now) that y was initialised, but the array initialisation was overwriting the initialisation of y. A note that the values you put into the array i affects the value of y. try the second struct below, which might give you C:\temp>dmd test.d C:\temp>test.exe 1065353216 on windows. Removing the initialisation from const array does "fix" it though, so this works: struct S1 { float a[10] = [1,1,1,1,1,1,1,1,1,1]; int y=5; } but this does not: struct S1 { const float[10] i = [1,1,1,1,1,1,1,1,1,1]; float a[10] = i; int y=5; } --
Nov 21 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1914


Jason Spashett <jason spashett.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Version|1.030                       |1.051



---
Still present. To restate the bug, here is a unit test, that should not fail:

unittest {
        struct A
        {
            const char[10] i = [0,0,0,0,0,0,0,0,0,0];

                        char[10] x = i;
            int y=5;
        }
        A a;

    }

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 09 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1914


Stewart Gordon <smjg iname.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Version|1.051                       |1.030



Please don't increase version numbers.
http://www.digitalmars.com/d/archives/digitalmars/D/bugs/bugzilla_usage_tips_10071.html

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 09 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1914


Don <clugdbug yahoo.com.au> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |clugdbug yahoo.com.au
           Severity|major                       |critical


-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 15 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1914


Don <clugdbug yahoo.com.au> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |patch



ROOT CAUSE: The glue layer is misinterpreting it as an array block assignment,
so for a 5 element array, it duplicates the array five times. It recognizes
that strings are slice assignments rather than block assignments, but it needs
to do the same thing for array literals.


PATCH(against DMD2 svn 382): todt.c, line 1001 in TypeSArray::toDtElem.


    }
-    else if (e->op != TOKstring)
+    else if (e->op != TOKstring && e->op != TOKarrayliteral)
    {   // Array block assignment (rather than slice assignment)
        for (i = 1; i < len; i++)
        {
        if (tbn->ty == Tstruct)
        {   pdt = tnext->toDt(pdt);
            while (*pdt)
            pdt = &((*pdt)->DTnext);
        }
        else
            pdt = e->toDt(pdt);
        }
    }

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 13 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1914




The patch (which has been included in D2, but not D1) was not correct -- it
didn't fix the case of an all-zero initializer, and also failed for
multi-dimensional array literals.

This patch, in todt.c, TypeSArray::toDtElem(), line 985, fixes this bug and
also fixes bug 3198. 

The first lines work by making sure we don't have an array of arrays.
3198 is fixed by removing the special case for structs in line 997:
-        if (tbn->ty == Tstruct)
-            tnext->toDt(pdt);
-        else
The main part of the patch is that we need to divide by the literal size.
And finally, undo the bad original patch.

PATCH: todt.c line 985
             pdt = &((*pdt)->DTnext);
         Type *tnext = next;
         Type *tbn = tnext->toBasetype();
-        while (tbn->ty == Tsarray)
+        // Count all dimensions, but stop if e is an array literal of
+        // arrays of the same type
+        while (tbn->ty == Tsarray && (!e || tbn != e->type->nextOf()))
         {   TypeSArray *tsa = (TypeSArray *)tbn;

             len *= tsa->dim->toInteger();
             tnext = tbn->nextOf();
             tbn = tnext->toBasetype();
        }
         if (!e)                         // if not already supplied
             e = tnext->defaultInit();   // use default initializer
-        if (tbn->ty == Tstruct)
-            tnext->toDt(pdt);
-        else
-            e->toDt(pdt);
+        e->toDt(pdt);          
         dt_optimize(*pdt);
+        if (e->op == TOKstring)
+            len /= ((StringExp *)e)->len;
+        if (e->op == TOKarrayliteral)
+            len /= ((ArrayLiteralExp *)e)->elements->dim;
         if ((*pdt)->dt == DT_azeros && !(*pdt)->DTnext)
         {
             (*pdt)->DTazeros *= len;
            pdt = &((*pdt)->DTnext);
        }
        else if ((*pdt)->dt == DT_1byte && (*pdt)->DTonebyte == 0 &&
!(*pdt)->DTnext)
        {
            (*pdt)->dt = DT_azeros;
             (*pdt)->DTazeros = len;
             pdt = &((*pdt)->DTnext);
         }
-        else if (e->op != TOKstring && e->op != TOKarrayliteral)
+        else
         {
             for (i = 1; i < len; i++)
             {

======================================
TEST CASES:

struct Bug1914a
{
    const char[10] i = [1,0,0,0,0,0,0,0,0,0];
    char[10] x = i;
    int y=5;
}

struct Bug1914b
{
    const char[10] i = [0,0,0,0,0,0,0,0,0,0];
    char[10] x = i;
    int y=5;
}

struct Bug1914c
{
    const char[2] i = ['a', 'b'];
    const char[2][3] j = [['x', 'y'], ['p', 'q'], ['r', 's']];
    const char[2][3] k = ["cd", "ef", "gh"];
    const char[2][3] l = [['x', 'y'], ['p'], ['h', 'k']];
    char[2][3] x = i;
    int y = 5;
    char[2][3] z = j;
    char[2][3] w = k;    
    int v=27;
    char[2][3] u = l;
    int t = 718;
}
struct T3198 {
   int g = 1;
}

class Foo3198 {
   int[5] x = 6;
   T3198[5] y = T3198(4);
}

void main()
{    
    Bug1914a a;
    assert(a.y==5, "bug 1914, non-zero init");
    Bug1914b b;
    assert(b.y==5, "bug 1914, zero init");
    Bug1914c c;
    assert(c.y==5, "bug 1914, multilevel init");
    assert(c.v==27, "bug 1914, multilevel init2");
    assert(c.x[2][1]=='b');
    assert(c.t==718, "bug 1914, multi3");
    assert(c.u[1][0]=='p');
    assert(c.u[1][1]==char.init);
    auto f = new Foo3198();
    assert(f.x[0]==6);
    assert(f.y[0].g==4, "bug 3198");
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 21 2011
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1914


Don <clugdbug yahoo.com.au> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |FIXED



Fixed
https://github.com/D-Programming-Language/dmd/commit/0c7bd71609735814f5bb410f903e454643ac260f

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 06 2011