Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
December 13, 2013 ubyte array changing values between calls? Possible bug? | ||||
---|---|---|---|---|
| ||||
I have the following code which is massively simplified from a larger type. The problem occurs between assigning the value to the type and retrieving it. The value is assigned through opAssign and the assert passes. When using a property to retrieve the same data the assert fails! import std.bitmanip; import std.stdio; import std.traits; struct IpAddress { private ubyte[] _octets; this(uint value) { this.opAssign(value); } public @property ubyte[] data() { assert(this._octets == [1, 2, 3, 4]); return this._octets; } public void opAssign(uint value) { this._octets = value.nativeToBigEndian(); assert(this._octets == [1, 2, 3, 4]); } } unittest { auto ipAddress = IpAddress(0x01020304); assert(ipAddress.data == [1, 2, 3, 4]); } Any ideas why? On a side note i also expected nativeToBigEndian to byte flip the hex literal, no idea why it hasn't, it's been a long day... I'm using MacOSX (Intel). Compiled with: rdmd --force -de -debug -main -property -unittest -w file.d |
December 13, 2013 Re: ubyte array changing values between calls? Possible bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Gary Willoughby | On Friday, 13 December 2013 at 16:37:51 UTC, Gary Willoughby wrote:
> I have the following code which is massively simplified from a larger type. The problem occurs between assigning the value to the type and retrieving it.
>
> The value is assigned through opAssign and the assert passes. When using a property to retrieve the same data the assert fails!
>
> import std.bitmanip;
> import std.stdio;
> import std.traits;
>
> struct IpAddress
> {
> private ubyte[] _octets;
>
> this(uint value)
> {
> this.opAssign(value);
> }
>
> public @property ubyte[] data()
> {
> assert(this._octets == [1, 2, 3, 4]);
> return this._octets;
> }
>
> public void opAssign(uint value)
> {
> this._octets = value.nativeToBigEndian();
> assert(this._octets == [1, 2, 3, 4]);
> }
> }
>
> unittest
> {
> auto ipAddress = IpAddress(0x01020304);
> assert(ipAddress.data == [1, 2, 3, 4]);
> }
>
> Any ideas why?
>
> On a side note i also expected nativeToBigEndian to byte flip the hex literal, no idea why it hasn't, it's been a long day... I'm using MacOSX (Intel).
>
> Compiled with: rdmd --force -de -debug -main -property -unittest -w file.d
opAssign is escaping a reference to its stack by assigning the static array to the slice _octets. Therefore, garbage.
|
December 13, 2013 Re: ubyte array changing values between calls? Possible bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin |
It works fine when using dup to the value returned by nativeToBigEndian:
public void opAssign(uint value)
{
this._octets = value.nativeToBigEndian().dup;
assert(this._octets == cast (ubyte[]) [1, 2, 3, 4]);
}
On 12/13/2013 06:35 PM, John Colvin wrote:
> On Friday, 13 December 2013 at 16:37:51 UTC, Gary Willoughby wrote:
>> I have the following code which is massively simplified from a larger
>> type. The problem occurs between assigning the value to the type and
>> retrieving it.
>>
>> The value is assigned through opAssign and the assert passes. When
>> using a property to retrieve the same data the assert fails!
>>
>> import std.bitmanip;
>> import std.stdio;
>> import std.traits;
>>
>> struct IpAddress
>> {
>> private ubyte[] _octets;
>>
>> this(uint value)
>> {
>> this.opAssign(value);
>> }
>>
>> public @property ubyte[] data()
>> {
>> assert(this._octets == [1, 2, 3, 4]);
>> return this._octets;
>> }
>>
>> public void opAssign(uint value)
>> {
>> this._octets = value.nativeToBigEndian();
>> assert(this._octets == [1, 2, 3, 4]);
>> }
>> }
>>
>> unittest
>> {
>> auto ipAddress = IpAddress(0x01020304);
>> assert(ipAddress.data == [1, 2, 3, 4]);
>> }
>>
>> Any ideas why?
>>
>> On a side note i also expected nativeToBigEndian to byte flip the hex
>> literal, no idea why it hasn't, it's been a long day... I'm using
>> MacOSX (Intel).
>>
>> Compiled with: rdmd --force -de -debug -main -property -unittest -w
>> file.d
>
> opAssign is escaping a reference to its stack by assigning the static
> array to the slice _octets. Therefore, garbage.
|
December 14, 2013 Re: ubyte array changing values between calls? Possible bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Rémy Mouëza | On Friday, 13 December 2013 at 18:01:53 UTC, Rémy Mouëza wrote:
>
> It works fine when using dup to the value returned by nativeToBigEndian:
> public void opAssign(uint value)
> {
> this._octets = value.nativeToBigEndian().dup;
> assert(this._octets == cast (ubyte[]) [1, 2, 3, 4]);
> }
>
As expected, as dup allocates a new array on the heap.
|
December 14, 2013 Re: ubyte array changing values between calls? Possible bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | On Friday, 13 December 2013 at 17:35:27 UTC, John Colvin wrote:
> On Friday, 13 December 2013 at 16:37:51 UTC, Gary Willoughby wrote:
>> I have the following code which is massively simplified from a larger type. The problem occurs between assigning the value to the type and retrieving it.
>>
>> The value is assigned through opAssign and the assert passes. When using a property to retrieve the same data the assert fails!
>>
>> import std.bitmanip;
>> import std.stdio;
>> import std.traits;
>>
>> struct IpAddress
>> {
>> private ubyte[] _octets;
>>
>> this(uint value)
>> {
>> this.opAssign(value);
>> }
>>
>> public @property ubyte[] data()
>> {
>> assert(this._octets == [1, 2, 3, 4]);
>> return this._octets;
>> }
>>
>> public void opAssign(uint value)
>> {
>> this._octets = value.nativeToBigEndian();
>> assert(this._octets == [1, 2, 3, 4]);
>> }
>> }
>>
>> unittest
>> {
>> auto ipAddress = IpAddress(0x01020304);
>> assert(ipAddress.data == [1, 2, 3, 4]);
>> }
>>
>> Any ideas why?
>>
>> On a side note i also expected nativeToBigEndian to byte flip the hex literal, no idea why it hasn't, it's been a long day... I'm using MacOSX (Intel).
>>
>> Compiled with: rdmd --force -de -debug -main -property -unittest -w file.d
>
> opAssign is escaping a reference to its stack by assigning the static array to the slice _octets. Therefore, garbage.
I'm not going to lie that has gone over my head a little. Could you explain it more simply please? I just want to totally understand the issue here. Thanks.
|
December 15, 2013 Re: ubyte array changing values between calls? Possible bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Gary Willoughby | On 12/14/2013 10:48 AM, Gary Willoughby wrote: > On Friday, 13 December 2013 at 17:35:27 UTC, John Colvin wrote: >>> public void opAssign(uint value) >>> { >>> this._octets = value.nativeToBigEndian(); >>> assert(this._octets == [1, 2, 3, 4]); >>> } >>> } >> opAssign is escaping a reference to its stack by assigning the static >> array to the slice _octets. Therefore, garbage. > > I'm not going to lie that has gone over my head a little. Could you > explain it more simply please? I just want to totally understand the > issue here. Thanks. According to documentation, nativeToBigEndian returns a static array (fixed-length array): http://dlang.org/phobos/std_bitmanip.html#.nativeToBigEndian It says "returns it as a ubyte[n] where n is the size of the given type." Since static arrays normally live on the stack, the returned array is a local array. As with any slice assignment, the assignment to this._octets in opAssign makes _octets a slice to the elements of that local array. Upon leaving opAssign that array is no more. So, _octets is left referring to elements that are long gone. :( Ali |
December 15, 2013 Re: ubyte array changing values between calls? Possible bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Sunday, 15 December 2013 at 00:21:37 UTC, Ali Çehreli wrote:
> On 12/14/2013 10:48 AM, Gary Willoughby wrote:
>
> > On Friday, 13 December 2013 at 17:35:27 UTC, John Colvin
> wrote:
>
> >>> public void opAssign(uint value)
> >>> {
> >>> this._octets = value.nativeToBigEndian();
> >>> assert(this._octets == [1, 2, 3, 4]);
> >>> }
> >>> }
>
> >> opAssign is escaping a reference to its stack by assigning
> the static
> >> array to the slice _octets. Therefore, garbage.
> >
> > I'm not going to lie that has gone over my head a little.
> Could you
> > explain it more simply please? I just want to totally
> understand the
> > issue here. Thanks.
>
> According to documentation, nativeToBigEndian returns a static array (fixed-length array):
>
> http://dlang.org/phobos/std_bitmanip.html#.nativeToBigEndian
>
> It says "returns it as a ubyte[n] where n is the size of the given type."
>
> Since static arrays normally live on the stack, the returned array is a local array.
>
> As with any slice assignment, the assignment to this._octets in opAssign makes _octets a slice to the elements of that local array. Upon leaving opAssign that array is no more. So, _octets is left referring to elements that are long gone. :(
>
> Ali
Ah right, that now makes perfect sense. Thanks all! :)
|
Copyright © 1999-2021 by the D Language Foundation