On Tuesday, 17 October 2017 at 23:59:19 UTC, Steven Schveighoffer wrote:
On 10/17/17 7:32 PM, flamencofantasy wrote:
On Tuesday, 17 October 2017 at 17:27:17 UTC, Biotronic wrote:
On Tuesday, 17 October 2017 at 15:33:02 UTC, drug wrote:
[...]

I have very little knowledge about sbrk, so here's my solution.

Tested on win32 and win64.

[...]

Try this;

unittest {
     int[5*1024] n;
     int* p = new int;

     assert(n.onStack);
     assert(!p.onStack);
}

The second is wrong. You are asserting that the storage of p is not on the stack, but it is.

What p *points at* is not on the stack.

So the correct call should be:

assert(!(*p).onStack);

or (IMO) less ugly: assert(!onStack(*p));

-Steve

No, the second is correct - the ref overload is only chosen when p is not implicitly castable to void*. In fact, the second assert passes, it's the first one that causes problems.

I've written an improved version, that probably still has problems. If flamencofantasy would like to point out other shortcomings, I'd love to learn.

module stackCheck;

private size_t stackStart;
enum size_t pageSize = 0x1000;

static this() {
    import core.stdc.stdlib : alloca;
    stackStart = cast(size_t)alloca(size_t.sizeof);
}

bool onStack(void* p) {
    size_t end = cast(size_t)&p;
    size_t pp = cast(size_t)p;
    size_t ss = stackStart;

    if (end > ss) {
        end &= ~(pageSize-1);
        ss  &= ~(pageSize-1);
        end += pageSize;
        return pp >= ss && pp <= end;
    } else {
        end &= ~(pageSize-1);
        ss  &= ~(pageSize-1);
        ss += pageSize;
        return pp <= ss && pp >= end;
    }
}

bool onStack(T)(ref T p) {
    return (&p).onStack;
}

unittest {
    int n;
    int* p = new int;

    assert(n.onStack);
    assert(!p.onStack);
}

unittest {
    int[5*1023] n;
    int* p = new int;

    assert(n.onStack);
    assert(!p.onStack);
}

Reply via email to