Jump to page: 1 2
Thread overview
testing if data is allocated on the stack or heap
Oct 17, 2017
drug
Oct 17, 2017
drug
Oct 17, 2017
Biotronic
Oct 17, 2017
drug
Oct 17, 2017
user1234
Oct 17, 2017
flamencofantasy
Oct 18, 2017
flamencofantasy
Oct 18, 2017
Biotronic
Oct 18, 2017
Biotronic
Oct 18, 2017
Jonathan M Davis
October 17, 2017
My code fails and I guess the reason is I have a slice to data in the stack and it becomes garbage in some moment. So I need a way to check where data is placed. Is it right that it can be done in linux using `sbrk` so that if the addr of data is less than `sbrk(0)` returning then data is on the stack and on the heap in other case?
October 17, 2017
https://run.dlang.io/is/vOh6YY
October 17, 2017
On Tuesday, 17 October 2017 at 15:33:02 UTC, drug wrote:
> My code fails and I guess the reason is I have a slice to data in the stack and it becomes garbage in some moment. So I need a way to check where data is placed. Is it right that it can be done in linux using `sbrk` so that if the addr of data is less than `sbrk(0)` returning then data is on the stack and on the heap in other case?

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

Tested on win32 and win64.

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) & ~(pageSize-1);
}

bool onStack(void* p) {
    size_t end = (cast(size_t)&p & ~(pageSize-1)) + pageSize;
    size_t pp = cast(size_t)p;

    if (end > stackStart) {
        return pp >= stackStart && pp <= end;
    } else {
        return pp <= stackStart && pp >= end;
    }
}

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

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

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

--
  Biotronic
October 17, 2017
17.10.2017 20:27, Biotronic пишет:
> 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) & ~(pageSize-1);
> }
> 
> bool onStack(void* p) {
>      size_t end = (cast(size_t)&p & ~(pageSize-1)) + pageSize;
>      size_t pp = cast(size_t)p;
> 
>      if (end > stackStart) {
>          return pp >= stackStart && pp <= end;
>      } else {
>          return pp <= stackStart && pp >= end;
>      }
> }
> 
> bool onStack(T)(ref T p) {
>      return (&p).onStack;
> }
> 
> unittest {
>      int n;
>      int* p = new int;
> 
>      assert(n.onStack);
>      assert(!p.onStack);
> }

Thanks! Your solution not only works but is portable also.
October 17, 2017
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.
>
> [...]

Nice solution. Is `stackStart` thread local on purpose?
October 17, 2017
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);
}
October 17, 2017
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
October 18, 2017
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

you misunderstood, the code is from biotronic's post, i just made a static array of 5kb to point out how it fails, in just one way out of a dozen other possibilities.
October 18, 2017
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);
}
October 18, 2017
On Tuesday, October 17, 2017 18:33:02 drug via Digitalmars-d-learn wrote:
> My code fails and I guess the reason is I have a slice to data in the stack and it becomes garbage in some moment. So I need a way to check where data is placed. Is it right that it can be done in linux using `sbrk` so that if the addr of data is less than `sbrk(0)` returning then data is on the stack and on the heap in other case?

In theory, @safe is supposed to help with this such that any code that sliced a static array would be @system or @trusted, which would seriously narrow down the search space when something goes wrong with memory, but the slicing of static arrays typically being treated as @safe is one of the major, outstanding bugs for @safe. It looks like it's now caught when simply returning a slice of a static array, but simply slicing a static array is still considered @safe (even though taking the address of a local variable does, and it's really the same thing).

So, if you try and use @safe throughout your code, you'll find _some_ of the potential memory problems but not all of them. All of the work that Walter has been doing with DIP 1000 should help though.

- Jonathan M Davis

« First   ‹ Prev
1 2