Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-21 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 22 May 2017 at 00:45:27 UTC, Adam D. Ruppe wrote:

On Monday, 22 May 2017 at 00:36:24 UTC, Stanislav Blinov wrote:
I can't think of any case where you'd want preconditions on 
destructor when the object is in .init state.


I think we're actually saying the same thing: I mean the 
destructor must be callable on .init so you might do like


struct Foo {
   int* ptr;
   ~this() {
  // might be called with ptr is null cuz of .init
  // so wanna check
  if(ptr !is null) free(ptr);
}
}


Ah, yes, exactly. The page is indeed the same one.

P.S. Though it's fine to call free with a null pointer :P


Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-21 Thread Adam D. Ruppe via Digitalmars-d-learn

On Monday, 22 May 2017 at 00:36:24 UTC, Stanislav Blinov wrote:
I can't think of any case where you'd want preconditions on 
destructor when the object is in .init state.


I think we're actually saying the same thing: I mean the 
destructor must be callable on .init so you might do like


struct Foo {
   int* ptr;
   ~this() {
  // might be called with ptr is null cuz of .init
  // so wanna check
  if(ptr !is null) free(ptr);
}
}


Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-21 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 22 May 2017 at 00:23:26 UTC, Adam D. Ruppe wrote:

On Sunday, 21 May 2017 at 14:13:20 UTC, Stanislav Blinov wrote:
Not if you either emplace() or blit Foo.init into all of the 
array elements.


You especially need to be safe calling ~this on Foo.init.


How so? .init is supposed to be destructible without question. 
destroy() calls in the runtime also blit the initializer back 
over the destructed objects. std.algorithm.move et al. 
specifically take advantage of .init (blit it over the moved-from 
object, so it can either be destructed or assigned something 
else).


I can't think of any case where you'd want preconditions on 
destructor when the object is in .init state.


Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-21 Thread Adam D. Ruppe via Digitalmars-d-learn

On Sunday, 21 May 2017 at 14:13:20 UTC, Stanislav Blinov wrote:
Not if you either emplace() or blit Foo.init into all of the 
array elements.


You especially need to be safe calling ~this on Foo.init.


Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-21 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 21 May 2017 at 23:59:08 UTC, Guillaume Piolat wrote:

On Sunday, 21 May 2017 at 12:48:10 UTC, Adam D. Ruppe wrote:

Any struct should be able to have its destructor called


Does this rule also applies to class objects?


Yes. If your destructor does modify the state, you should expect 
it to be called and have the state ready for it.


When you're using the GC, destructors *may* not be called under 
certain conditions:


http://dlang.org/spec/class.html#destructors

But there's no stopping you from destructing manually (via 
destroy() call), or by allocating classes manually via malloc or 
on the stack.


Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-21 Thread Guillaume Piolat via Digitalmars-d-learn

On Sunday, 21 May 2017 at 12:48:10 UTC, Adam D. Ruppe wrote:

Any struct should be able to have its destructor called


Does this rule also applies to class objects?


Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-21 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 21 May 2017 at 12:48:10 UTC, Adam D. Ruppe wrote:

On Saturday, 20 May 2017 at 10:48:54 UTC, Gary Willoughby wrote:

// Why is this._foo null here???


The others have answered why and what to do, but note that 
according to the spec, that any struct should be able to have 
its destructor called, so you should do a null check in there 
anyway.


Not if you either emplace() or blit Foo.init into all of the 
array elements.


Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-21 Thread Adam D. Ruppe via Digitalmars-d-learn

On Saturday, 20 May 2017 at 10:48:54 UTC, Gary Willoughby wrote:

// Why is this._foo null here???


The others have answered why and what to do, but note that 
according to the spec, that any struct should be able to have its 
destructor called, so you should do a null check in there anyway.


Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-21 Thread Eduard Staniloiu via Digitalmars-d-learn

On Saturday, 20 May 2017 at 10:48:54 UTC, Gary Willoughby wrote:
Looks like you would want to use emplace [0] here.


public this(int n)
{
this._data = (cast(Foo*) calloc(n, Foo.sizeof))[0 .. n];

foreach(ref element; this._data)
{
auto tmp = Foo(1);
element = tmp;
}
}


Cheers,
Eduard

[0] - https://dlang.org/phobos/std_conv.html#.emplace.3


Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-20 Thread Gary Willoughby via Digitalmars-d-learn

On Saturday, 20 May 2017 at 12:25:39 UTC, Stanislav Blinov wrote:

Oof. Dangerous stuff.


:)

Thanks for the heads up but I think I'm covering all cases in my 
main code.


Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-20 Thread Gary Willoughby via Digitalmars-d-learn

On Saturday, 20 May 2017 at 11:15:57 UTC, Moritz Maxeiner wrote:
Because `element = tmp` destroys `element`, which you allocated 
filled with zeroes.

The destructor will run for each `element`.


Right, I get it because the destructors running on the struct 
that is being replaced. Doh!


Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-20 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 20 May 2017 at 10:48:54 UTC, Gary Willoughby wrote:
In the following code, the `_foo` pointer (of the Foo struct) 
is null in the first call to the destructor. Why is this? I 
think it's got something to do with the foreach loop but I'm 
not sure. Any ideas?


Oof. Dangerous stuff. As Moritz pointed out, default opAssign 
will call the destructor on Foo. I should, however, elaborate 
further. You're dealing with uninitialized data. calloc() gives 
you zero-initialized block, which is not necessarily how Foo.init 
would look (it does in this case, but that's not true in general 
case).
malloc() gives you a potentially garbage-filled block, which is 
even more dangerous.


When filling an array of uninitialized values, use 
std.algorithm.moveEmplace(src, dst) instead of assignment. And, 
if you have destructors, you have to call the destructors 
manually when you free the array.
Furthermore, since Bar._data is an array of Foos, and Foo has a 
pointer in it, you might want to register the Bar._data array 
with the GC (GC.addRange, GC.removeRange). Unless you're willing 
to manually make sure that GC *never* sees those pointers.


Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-20 Thread Moritz Maxeiner via Digitalmars-d-learn

On Saturday, 20 May 2017 at 10:48:54 UTC, Gary Willoughby wrote:
In the following code, the `_foo` pointer (of the Foo struct) 
is null in the first call to the destructor. Why is this? I 
think it's got something to do with the foreach loop but I'm 
not sure. Any ideas?


struct Bar
{
private Foo[] _data;

public this(int n)
{
this._data = (cast(Foo*) calloc(n, Foo.sizeof))[0 .. n];

foreach(ref element; this._data)
{
auto tmp = Foo(1);
element = tmp;
}
}
}


Because `element = tmp` destroys `element`, which you allocated 
filled with zeroes.

The destructor will run for each `element`.


Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-20 Thread Gary Willoughby via Digitalmars-d-learn
In the following code, the `_foo` pointer (of the Foo struct) is 
null in the first call to the destructor. Why is this? I think 
it's got something to do with the foreach loop but I'm not sure. 
Any ideas?



import std.stdio;
import core.stdc.stdlib : malloc, calloc, free;

struct Foo
{
public int* _foo;

public this(int n)
{
this._foo  = cast(int*) malloc(int.sizeof);
writefln("ctor: %x", this._foo);
}

public this(this)
{
writefln("post blit: %x", this._foo);
}

public ~this()
{
// Why is this._foo null here???
writefln("dtor: %x", this._foo);
}
}

struct Bar
{
private Foo[] _data;

public this(int n)
{
this._data = (cast(Foo*) calloc(n, Foo.sizeof))[0 .. n];

foreach(ref element; this._data)
{
auto tmp = Foo(1);
element = tmp;
}
}
}

void main(string[] args)
{
auto bar = Bar(1);
}