[Issue 8556] New: Using take results in a corrupted call to opSlice

d-bugmail at puremagic.com d-bugmail at puremagic.com
Fri Aug 17 02:41:20 PDT 2012


http://d.puremagic.com/issues/show_bug.cgi?id=8556

           Summary: Using take results in a corrupted call to opSlice
           Product: D
           Version: unspecified
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody at puremagic.com
        ReportedBy: jmdavisProg at gmx.com


--- Comment #0 from Jonathan M Davis <jmdavisProg at gmx.com> 2012-08-17 02:41:15 PDT ---
Okay. This program

import std.algorithm;
import std.range;
import std.stdio;
import std.string;
import std.traits;

struct Cycle(Range)
if (isForwardRange!(Unqual!Range) && !isInfinite!(Unqual!Range))
{
    alias Unqual!Range R;

    R _original;
    size_t _index;

    this(R input, size_t index = 0) { _original = input; _index = index; }

    @property auto ref front()
    {
        return _original[_index % _original.length];
    }

    enum bool empty = false;

    void popFront() { ++_index; }

    auto opSlice(size_t i, size_t j)
    {
        assert(j >= i, format("%s %s %s", i, j, _index));
        writefln("%s %s %s", i, j, _index);
        return takeExactly(typeof(this)(_original.save, _index + i), j - i);
    }
}

Cycle!R cycle(R)(R input, size_t index = 0)
    if (isRandomAccessRange!(Unqual!R) && !isInfinite!(Unqual!R))
{
    return Cycle!R(input, index);
}


void main()
{
    uint[] arr = [1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U];
    auto t = take(cycle(arr), 20);

    auto cx = cycle(arr);
    auto slice = cx[23 .. 33];
    assert(equal(slice, [4, 5, 6, 7, 8, 9, 10, 1, 2, 3]), format("%s",
array(slice)));
}

seems to give different results depending on the architecture, and small tweaks
to it seem to result in different results fairly easily. Given the code above,
it should print out

23 33 0

and pass the assertions, but right now it prints out

core.exception.AssertError at q.d(28): 140464871555008 10 0

and the exact number for the first index varies between runs of the program. If
I were to change opSlice to take ints, then I get

0 10 0
core.exception.AssertError at q.d(48): [1,2,3,4,5,6,7,8,9,10]

and the results actually seem to be consistent.

If I remove the call to take, then the code works just fine. So, it looks like
for some reason, that call to take is resulting in the indices to opSlice being
corrupted, and rather than 22 and 33, it's more or less random, depending on
what other code is there (code which should have _zero_ effect on the indices)
and potentially changing between runs of the program.

Interestingly enough, if I compile with -O, I get this error in opSlice:

q.d(28): Error: variable j used before set
q.d(28): Error: variable i used before set

and if I compile with -inline, I get

q.d(28): Error: function q.Cycle!(uint[]).Cycle.opSlice is a nested function
and cannot be accessed from D main
q.d(28): Error: function q.Cycle!(uint[]).Cycle.opSlice is a nested function
and cannot be accessed from D main
q.d(28): Error: function q.Cycle!(uint[]).Cycle.opSlice is a nested function
and cannot be accessed from D main
q.d(28): Error: function q.Cycle!(uint[]).Cycle.opSlice is a nested function
and cannot be accessed from D main
q.d(29): Error: function q.Cycle!(uint[]).Cycle.opSlice is a nested function
and cannot be accessed from D main
q.d(29): Error: function q.Cycle!(uint[]).Cycle.opSlice is a nested function
and cannot be accessed from D main
q.d(30): Error: function q.Cycle!(uint[]).Cycle.opSlice is a nested function
and cannot be accessed from D main
q.d(30): Error: function q.Cycle!(uint[]).Cycle.opSlice is a nested function
and cannot be accessed from D main
q.d(30): Error: function q.Cycle!(uint[]).Cycle.opSlice is a nested function
and cannot be accessed from D main
dmd: glue.c:735: virtual void FuncDeclaration::toObjFile(int): Assertion
`!vthis->csym' failed.
Aborted

So, maybe there's something wrong with the lowering code? take does call the
slice operator, but using the slice operator twice rather than calling take and
then using it seems to work just fine. All in all, this looks really weird.

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


More information about the Digitalmars-d-bugs mailing list