digitalmars.D.learn - testing if data is allocated on the stack or heap
- drug (5/5) Oct 17 2017 My code fails and I guess the reason is I have a slice to data in the
- drug (1/1) Oct 17 2017 https://run.dlang.io/is/vOh6YY
- Biotronic (31/37) Oct 17 2017 I have very little knowledge about sbrk, so here's my solution.
- drug (2/34) Oct 17 2017 Thanks! Your solution not only works but is portable also.
- user1234 (2/7) Oct 17 2017 Nice solution. Is `stackStart` thread local on purpose?
- flamencofantasy (8/13) Oct 17 2017 Try this;
- Steven Schveighoffer (8/27) Oct 17 2017 The second is wrong. You are asserting that the storage of p is not on
- flamencofantasy (5/33) Oct 17 2017 you misunderstood, the code is from biotronic's post, i just made
- Biotronic (46/74) Oct 18 2017 No, the second is correct - the ref overload is only chosen when
- Biotronic (7/7) Oct 18 2017 It's worth pointing out, btw, that the main reason for this code
- Jonathan M Davis (13/18) Oct 18 2017 In theory, @safe is supposed to help with this such that any code that
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?
Oct 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
Oct 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.
Oct 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:Nice solution. Is `stackStart` thread local on purpose?[...]I have very little knowledge about sbrk, so here's my solution. Tested on win32 and win64. [...]
Oct 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:Try this; unittest { int[5*1024] n; int* p = new int; assert(n.onStack); assert(!p.onStack); }[...]I have very little knowledge about sbrk, so here's my solution. Tested on win32 and win64. [...]
Oct 17 2017
On 10/17/17 7:32 PM, flamencofantasy wrote:On Tuesday, 17 October 2017 at 17:27:17 UTC, Biotronic wrote: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)); -SteveOn Tuesday, 17 October 2017 at 15:33:02 UTC, drug wrote:Try this; unittest { int[5*1024] n; int* p = new int; assert(n.onStack); assert(!p.onStack); }[...]I have very little knowledge about sbrk, so here's my solution. Tested on win32 and win64. [...]
Oct 17 2017
On Tuesday, 17 October 2017 at 23:59:19 UTC, Steven Schveighoffer wrote:On 10/17/17 7:32 PM, flamencofantasy wrote: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.On Tuesday, 17 October 2017 at 17:27:17 UTC, Biotronic wrote: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)); -SteveOn Tuesday, 17 October 2017 at 15:33:02 UTC, drug wrote:Try this; unittest { int[5*1024] n; int* p = new int; assert(n.onStack); assert(!p.onStack); }[...]I have very little knowledge about sbrk, so here's my solution. Tested on win32 and win64. [...]
Oct 17 2017
On Tuesday, 17 October 2017 at 23:59:19 UTC, Steven Schveighoffer wrote:On 10/17/17 7:32 PM, flamencofantasy wrote: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); }On Tuesday, 17 October 2017 at 17:27:17 UTC, Biotronic wrote: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)); -SteveOn Tuesday, 17 October 2017 at 15:33:02 UTC, drug wrote:Try this; unittest { int[5*1024] n; int* p = new int; assert(n.onStack); assert(!p.onStack); }[...]I have very little knowledge about sbrk, so here's my solution. Tested on win32 and win64. [...]
Oct 18 2017
It's worth pointing out, btw, that the main reason for this code is to help drug diagnose his or her problem, not to be the be-all, end-all of stack identifying functions. :) It will of course not correctly identify pointers to variables on other threads' stacks, and fiber stacks probably trip it up bad. -- Biotronic
Oct 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
Oct 18 2017