June 10, 2022

On Friday, 10 June 2022 at 14:56:24 UTC, Steven Schveighoffer wrote:

>

On 6/10/22 3:46 AM, Mike Parker wrote:

>

I think this is a case where having a warning that's on by default, and which can be explicitly disabled, is useful. "Blah blah .init blah blah. See link-to-something-in-docs. Is this what you intended?"

Here the language is being extremely unsafe.

Not only is the field shared between instances, it's shared across instances in different threads.

Discovered circa 2009: https://issues.dlang.org/show_bug.cgi?id=2947

Thanks for the pointer. #dbugfix 2947

>

It should be illegal to declare a field this way that has mutable references without being shared. End of story.

June 11, 2022
On Friday, 10 June 2022 at 07:49:43 UTC, Mike Parker wrote:
> ...
> And it *is* documented:
>
>> Struct fields are by default initialized to whatever the Initializer for the field is, and if none is supplied, to the default initializer for the field's type.
>> The default initializers are evaluated at compile time.
>
> https://dlang.org/spec/struct.html#default_struct_init

Hmm I understand the text but for this intializers I was expecting new address with length 5, for example:

import std.stdio;

struct S{
    int[] arr = new int[](5);
    int[2] arr2;
}

void main(){
    S s1, s2;

    s2.arr[0] = 42;
    writeln(s1.arr[0], " address: ", &s1.arr[0]);
    writeln(s2.arr[0], " address: ", &s2.arr[0]);

    s2.arr2[0] = 10;
    writeln(s1.arr2[0], " address: ", &s1.arr2[0]);
    writeln(s2.arr2[0], " address: ", &s2.arr2[0]);
}

Prints:

42 address: 5586F5BD9CC0
42 address: 5586F5BD9CC0
 0 address: 7FFFC65C7A20
10 address: 7FFFC65C7A40


And as it can be seen: s1.arr and s2.arr shares the same address.

So, in the case of "int[] arr = new int[](5)", an array of length 5 of type int will be instantiated and its address will be shared among whoever instantiates "S" and be pointed and accessed through arr.

In the second case, "int[2] arr2", 2 consecutive integer spaces in memory will be allocate independently for each "instantiation" of "S", so different address.

I never saw this before (I mean I never wrote the first case), I'm used to the "int[2] arr2;" way of declaring it, but if I had looked this code without knowing this, I'd be certain that s1.arr and s2.arr would have different addresses.

This is a bit weird (At least for a newbie like me), I really think the compiler should emit an warning about this.

Matheus.
June 11, 2022

On Saturday, 11 June 2022 at 01:14:06 UTC, matheus wrote:

>

So, in the case of "int[] arr = new int", an array of length 5 of type int will be instantiated and its address will be shared among whoever instantiates "S" and be pointed and accessed through arr.

In the second case, "int[2] arr2", 2 consecutive integer spaces in memory will be allocate independently for each "instantiation" of "S", so different address.

I never saw this before (I mean I never wrote the first case), I'm used to the "int[2] arr2;" way of declaring it, but if I had looked this code without knowing this, I'd be certain that s1.arr and s2.arr would have different addresses.

That's because static arrays are allocated as part of the instance:

struct Foo {
    int[] dyn;
}

struct Bar {
    int[10] stat;
}

assert(Foo.sizeof == 16);
assert(Bar.sizeof == 40);
>

This is a bit weird (At least for a newbie like me), I really think the compiler should emit an warning about this.

At it's core this is just a matter of knowing how two specific language features behave (allocation of static vs. dynamic arrays coupled with member field initialization). If you aren't aware of it and it bites you, then you learn about it and you know it. So would you then really want a warning every time you initialize a static array field?

People getting bit by new in field initialization often enough that I think a warning would be helpful. But any such warnings need to be enabled by default to be useful, and must have an off switch for people who don't need them. So the question in each case would be, where's the line between helpful and annoying?

The compiler should be as helpful as it can, but it has to be helpful without getting in the way. There's a significant amount of learning by trial and error in any programming language. So I think there has to be a distinction between things like "easy to do by accident even when you know the deal" and "once you learn it, you're unlikely to do it again".

June 11, 2022
On Saturday, 11 June 2022 at 01:52:58 UTC, Mike Parker wrote:
> ...
> That's because static arrays are allocated as part of the instance:
> ...

Yes I understood the problem, but the naive me was thinking that in this example:

struct S{
    int[] arr = new int[](5);
}

For some reason this would be transformed as a statically "int[5] arr" in the case of structs.

But now I see that's not the case and "arr" points to whatever was allocated by "new", and will share across the instances of S (Since it's the same address).

> ... So would you then really want a warning every time you initialize a static array field?

Well would this be annoying? Yes, mainly if I already know this, but if not, then it would be like a nice to know warning for newbies like myself. By the way this would be only in the cases that a static array field being initialized with dynamic allocation like in the case of struct declaration, not on every place.

> ...
> So the question in each case would be, where's the line between helpful and annoying?

Well I like to think about this like the "-Wall" flag in C compilers, you need to go for it, and you just dismiss the warning in such case if you don't agree or know what you're doing.

> ...
> The compiler should be as helpful as it can, but it has to be helpful without getting in the way. There's a significant amount of learning by trial and error in any programming language. So I think there has to be a distinction between things like "easy to do by accident even when you know the deal"  and "once you learn it, you're unlikely to do it again".

Yes no doubt about it, by the way like I said, I never used this form to initialize fields in structs, I always used the "T[n] member", but in this particular case the result would have been very different from what I expected.

Anyway I'm always lurking around this Forum and learning new things.

Thanks,

Matheus.

PS: I'm ESL so sorry for my English mistakes.
June 11, 2022

On Saturday, 11 June 2022 at 02:22:28 UTC, matheus wrote:

>

Well would this be annoying? Yes, mainly if I already know this, but if not, then it would be like a nice to know warning for newbies like myself. By the way this would be only in the cases that a static array field being initialized with dynamic allocation like in the case of struct declaration, not on every place.

I agree...

I'd be wrong too if I didn't know that while reading the code. I think there should be a warning when compiling.

Really, is it so hard to put up a warning?

SDB@79

June 11, 2022

On Saturday, 11 June 2022 at 01:52:58 UTC, Mike Parker wrote:

>

People getting bit by new in field initialization often enough that I think a warning would be helpful.

The problem is so much bigger because it is not just a case of being aware not to use new in member initialisers. As you see in my second example in https://forum.dlang.org/post/ogvubzgprghefclgluce@forum.dlang.org there is no new anywhere. In fact you could say an effort has been made to do the right thing in struct A where the allocation has been moved to the constructor (a strategy that is not always available because structs don’t have default constructors) yet we fell into the same trap.

My point is that this problem can be buried deep down under multiple layers and you can’t really ever be sure that there isn’t a problem in your massive code base.

>

But any such warnings need to be enabled by default to be useful, and must have an off switch for people who don't need them. So the question in each case would be, where's the line between helpful and annoying?

So that’s why I used “why” in the title of this thread, which I haven’t seen an answer to yet. What is the practical case where that warning would be annoying? When would you actually want this behaviour?

— Bastiaan.

June 11, 2022

On Saturday, 11 June 2022 at 10:37:30 UTC, Bastiaan Veelo wrote:

>

So that’s why I used “why” in the title of this thread, which I haven’t seen an answer to yet. What is the practical case where that warning would be annoying? When would you actually want this behaviour?

After actually stopping to think about it (my earlier responses were reflexive), I agree with your initial assessment that it should be an error. It really only makes sense to allow the dynamic allocation if the fields are immutable and, in the case of arrays, the initializer is a literal.

June 11, 2022

On Saturday, 11 June 2022 at 10:52:58 UTC, Mike Parker wrote:

>

I agree with your initial assessment that it should be an error. It really only makes sense to allow the dynamic allocation if the fields are immutable and, in the case of arrays, the initializer is a literal.

👍

1 2
Next ›   Last »