return *(cast(T*)vPtr) and OutOfMemoryException

Frits van Bommel fvbommel at REMwOVExCAPSs.nl
Sat Feb 14 08:58:35 PST 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 failed

Here 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 good

This 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


More information about the Digitalmars-d-learn mailing list