| Thread overview | |||||
|---|---|---|---|---|---|
|
February 14, 2009 return *(cast(T*)vPtr) and OutOfMemoryException | ||||
|---|---|---|---|---|
| ||||
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
| ||||
February 14, 2009 Re: return *(cast(T*)vPtr) and OutOfMemoryException | ||||
|---|---|---|---|---|
| ||||
Posted in reply to TSalm | 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 | |||
February 14, 2009 Re: return *(cast(T*)vPtr) and OutOfMemoryException | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Frits van Bommel | 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 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
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply