digitalmars.D.learn - return *(cast(T*)vPtr) and OutOfMemoryException
- TSalm (29/29) Feb 14 2009 Hello,
- Frits van Bommel (14/58) Feb 14 2009 Here you're storing a pointer to a non-ref parameter. This is the bug;
- TSalm (4/47) Feb 14 2009 Excellent explication !
Hello, In the code below, why the first Stdout throws a Exception when the second doesn't ? /* -------- CODE -------- */ import tango.io.Stdout; struct VoidPtr(T) { void* vPtr; void value(T val) { vPtr = &val; } T value() { return *(cast(T*)vPtr); } } void main() { VoidPtr!(char[][]) vPtr ; char[][] arr = [ "hello" , "you" ]; vPtr.value = arr ; Stdout( vPtr.value ).newline; // <-- [tango.core.Exception.OutOfMemoryException: Memory allocation failed Stdout( *(cast(char[][]*) vPtr.vPtr ) ); // <-- This works good } /* ------ END CODE ------ */ Thanks in advance for your help, TSalm
Feb 14 2009
TSalm wrote:Hello, In the code below, why the first Stdout throws a Exception when the second doesn't ? /* -------- CODE -------- */ import tango.io.Stdout; struct VoidPtr(T) { void* vPtr; void value(T val) { vPtr = &val;Here you're storing a pointer to a non-ref parameter. This is the bug; the parameter itself is implicitly deallocated on returning from this function. Change to 'ref T val' to fix it. Essentially, an array is a struct { size_t length; T ptr; }. This means 'val' refers to a copy in the stack frame of this function, not to 'arr' in main().} T value() { return *(cast(T*)vPtr); } } void main() { VoidPtr!(char[][]) vPtr ; char[][] arr = [ "hello" , "you" ]; vPtr.value = arr ; Stdout( vPtr.value ).newline; // <-- [tango.core.Exception.OutOfMemoryException: Memory allocation failedHere you're calling a new function, overwriting *vPtr with something else (probably vptr itself), resulting in a huge array when you try to read it later.Stdout( *(cast(char[][]*) vPtr.vPtr ) ); // <-- This works goodThis reads the (implicitly deallocated) 'val' parameter before it gets overwritten, hiding the bug. It's still there: just because the code doesn't crash doesn't mean it's correct.} /* ------ END CODE ------ */ Thanks in advance for your help, TSalm
Feb 14 2009
Excellent explication ! Thank you Frits Le Sat, 14 Feb 2009 17:58:35 +0100, Frits van Bommel <fvbommel remwovexcapss.nl> a écrit:TSalm wrote:Hello, In the code below, why the first Stdout throws a Exception when the second doesn't ? /* -------- CODE -------- */ import tango.io.Stdout; struct VoidPtr(T) { void* vPtr; void value(T val) { vPtr = &val;Here you're storing a pointer to a non-ref parameter. This is the bug; the parameter itself is implicitly deallocated on returning from this function. Change to 'ref T val' to fix it. Essentially, an array is a struct { size_t length; T ptr; }. This means 'val' refers to a copy in the stack frame of this function, not to 'arr' in main().} T value() { return *(cast(T*)vPtr); } } void main() { VoidPtr!(char[][]) vPtr ; char[][] arr = [ "hello" , "you" ]; vPtr.value = arr ; Stdout( vPtr.value ).newline; // <-- [tango.core.Exception.OutOfMemoryException: Memory allocation failedHere you're calling a new function, overwriting *vPtr with something else (probably vptr itself), resulting in a huge array when you try to read it later.Stdout( *(cast(char[][]*) vPtr.vPtr ) ); // <-- This works goodThis reads the (implicitly deallocated) 'val' parameter before it gets overwritten, hiding the bug. It's still there: just because the code doesn't crash doesn't mean it's correct.} /* ------ END CODE ------ */ Thanks in advance for your help, TSalm
Feb 14 2009