Jump to page: 1 2
Thread overview
Re: bug in assigning to dynamic array element
Nov 01, 2014
Iain Buclaw
Nov 01, 2014
ketmar
Nov 01, 2014
Iain Buclaw
Nov 01, 2014
ketmar
Nov 01, 2014
Iain Buclaw
Nov 02, 2014
Dan Olson
Nov 03, 2014
ketmar
Nov 04, 2014
ketmar
Nov 01, 2014
ketmar
Nov 01, 2014
Iain Buclaw
Nov 04, 2014
ketmar
Nov 01, 2014
ketmar
November 01, 2014
On 1 November 2014 09:03, ketmar via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> Hello.
>
> let's run this code:
>
>       info.list[idx] = saveIt(info, count-1); //!!!

You could use:

emplace(&info.list[idx], saveIt(info, count-1));
November 01, 2014
On Sat, 1 Nov 2014 12:34:50 +0000
Iain Buclaw via Digitalmars-d <digitalmars-d@puremagic.com> wrote:

> On 1 November 2014 09:03, ketmar via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> > Hello.
> >
> > let's run this code:
> >
> >       info.list[idx] = saveIt(info, count-1); //!!!
> 
> You could use:
> 
> emplace(&info.list[idx], saveIt(info, count-1));
i know some workarounds, i just want to know how can i explain this nonsense to newcomers. "please, remember that you can't safely assign values to array elements"? this is one of the best ways to turn 'em off. "wut? are you kidding? that's what they call 'safe language'? thank you, but no. they can't do even array assign, what a..." ;-)


November 01, 2014
On 1 November 2014 12:39, ketmar via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On Sat, 1 Nov 2014 12:34:50 +0000
> Iain Buclaw via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
>> On 1 November 2014 09:03, ketmar via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>> > Hello.
>> >
>> > let's run this code:
>> >
>> >       info.list[idx] = saveIt(info, count-1); //!!!
>>
>> You could use:
>>
>> emplace(&info.list[idx], saveIt(info, count-1));
> i know some workarounds, i just want to know how can i explain this nonsense to newcomers. "please, remember that you can't safely assign values to array elements"?

Or how about: Every side effect is evaluated LTR.  So whatever you do, don't have LHS-altering side-effects on the RHS.  It may be over the top to explain simply that it is questionable and potentially wrong to assume that things happen in a given order.  But you may not be too far off the mark to explain that when the need for an explicit order is required, do it yourself.  Avoid surprises.
November 01, 2014
On Sat, 1 Nov 2014 12:58:26 +0000
Iain Buclaw via Digitalmars-d <digitalmars-d@puremagic.com> wrote:

> Or how about: Every side effect is evaluated LTR.  So whatever you do, don't have LHS-altering side-effects on the RHS.  It may be over the top to explain simply that it is questionable and potentially wrong to assume that things happen in a given order.  But you may not be too far off the mark to explain that when the need for an explicit order is required, do it yourself.  Avoid surprises.
the thing is that dynamic arrays tries to disguise themselves as static arrays. so programmer have not only to know the compiler internals to explain what's going on, but he have to track all types by himself. this is bad for all means.

if such assigns will be left untouched, this will inevitably lead to subtle bugs that are really hard to find.

if such assigns will be forbidden only for dynamic arrays, any sane person will question that. "so i can do this for char[4] and can't do this for char[]? and why do you have the same syntax for completely different things then?"

if such assigns will be forbidden for any arrays... this is even worse. "what? your shiny language can't do what even the simpliest C compiler can do? now try to convince me that D is not a toy."


November 01, 2014
On 1 November 2014 13:05, ketmar via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On Sat, 1 Nov 2014 12:58:26 +0000
> Iain Buclaw via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
>> Or how about: Every side effect is evaluated LTR.  So whatever you do, don't have LHS-altering side-effects on the RHS.  It may be over the top to explain simply that it is questionable and potentially wrong to assume that things happen in a given order.  But you may not be too far off the mark to explain that when the need for an explicit order is required, do it yourself.  Avoid surprises.
> the thing is that dynamic arrays tries to disguise themselves as static arrays. so programmer have not only to know the compiler internals to explain what's going on, but he have to track all types by himself. this is bad for all means.
>

They both infact meet each other somewhere in the middle, but that's another matter.

This doesn't stop the fact that unless you realise that dynamic arrays are *dynamic* - as in, the base .ptr can and will likely change if you grow the array .length during midflight of an assignment - you will run into these problems.

So your only solution is to pre-allocate the ptr in the GC to prevent the .ptr from moving because it has been reallocated to another area to accommodate growth.


> if such assigns will be left untouched, this will inevitably lead to subtle bugs that are really hard to find.
>

Changing the behaviour may also create new bugs that are really hard to find.


> if such assigns will be forbidden only for dynamic arrays, any sane person will question that. "so i can do this for char[4] and can't do this for char[]? and why do you have the same syntax for completely different things then?"
>

Some people are used to this idea. eg:

std::cout << "foo";

> if such assigns will be forbidden for any arrays... this is even worse. "what? your shiny language can't do what even the simpliest C compiler can do? now try to convince me that D is not a toy."

That - for sure - is where you're wrong. :-)


#include <assert.h>
#include <stdlib.h>

template <typename T>
struct Array
{
    size_t length;
    T* ptr;

    Array(int size) {
        this->length = 0;
        this->ptr = new T[size];
    }
};

int saveIt(Array<size_t>& list)
{
  list = Array<size_t>(1);
  return 666;
}

int main()
{
  Array<size_t> list = Array<size_t>(1);
  list.ptr[0] = saveIt(list);
  assert(list.ptr[0] == 666);
}


Looks like C++ works in the same way as D!  Go figure!

Regards
Iain.
November 01, 2014
On Sat, 1 Nov 2014 13:56:49 +0000
Iain Buclaw via Digitalmars-d <digitalmars-d@puremagic.com> wrote:

> So your only solution is to pre-allocate the ptr in the GC to prevent the .ptr from moving because it has been reallocated to another area to accommodate growth.
if this will be left as is, the only solution is to drop D. i already know the language that is filled with UBs, and there are alot of code written in that language already.

> > if such assigns will be left untouched, this will inevitably lead to subtle bugs that are really hard to find.
> >
> Changing the behaviour may also create new bugs that are really hard to find.
please, what sane use can be for this misfeature? it has no sense, it's not doing anything useful and it's plainly wrong.

> > if such assigns will be forbidden only for dynamic arrays, any sane person will question that. "so i can do this for char[4] and can't do this for char[]? and why do you have the same syntax for completely different things then?"
> Some people are used to this idea. eg:
> 
> std::cout << "foo";
that's why i dropped C++. ;-)

> > if such assigns will be forbidden for any arrays... this is even worse. "what? your shiny language can't do what even the simpliest C compiler can do? now try to convince me that D is not a toy."
> That - for sure - is where you're wrong. :-)
i was talking about C, not that abomination. but if D will compete with C++ for the quirks... than C++ is a winner. ;-)

besides, i clearly see 'list.ptr' there. i don't see 'dynArray.ptr' in D code. if i was using '.ptr' directly and it changes by the way... ok, it was my fault. but i never used '.ptr' in my sample!


November 01, 2014
On 1 November 2014 14:19, ketmar via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On Sat, 1 Nov 2014 13:56:49 +0000
> Iain Buclaw via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
>> > if such assigns will be forbidden for any arrays... this is even worse. "what? your shiny language can't do what even the simpliest C compiler can do? now try to convince me that D is not a toy."
>> That - for sure - is where you're wrong. :-)
> i was talking about C, not that abomination. but if D will compete with C++ for the quirks... than C++ is a winner. ;-)
>
> besides, i clearly see 'list.ptr' there. i don't see 'dynArray.ptr' in D code. if i was using '.ptr' directly and it changes by the way... ok, it was my fault. but i never used '.ptr' in my sample!

You can clearly see the 'list.length' though.  You can't possibly go off the assumption that if you grow the size of a dynamic array, it's area in memory won't be relocated.
November 01, 2014
On Sat, 1 Nov 2014 14:44:54 +0000
Iain Buclaw via Digitalmars-d <digitalmars-d@puremagic.com> wrote:

> You can clearly see the 'list.length' though.  You can't possibly go off the assumption that if you grow the size of a dynamic array, it's area in memory won't be relocated.
i don't even want to know if that was dynamic or static array! why should i remember that? isn't type checking is what compiler does for us? ;-)

dynamic arrays either should not look like static arrays, or should work as static arrays. it's ok for class/struct opAssign() to has some side effects, but it's not ok for built-in things. compiler is perfectly able to at least emit error there. or make that code work as it should work by dereferencing .ptr before doing 'mov' and not before calling `saveIt()`.

i don't even want to know about that '.ptr' thing after all. the sample should either consistently not updating the array element, or consistenly updating it, following the principle of the least surprise.


November 02, 2014
Like D, Java is LTR evaluation for assignment, and I think C# too.  A similar situation to OP code can be created in Java by reassigning an array reference in saveIt().
November 03, 2014
On Sun, 02 Nov 2014 09:25:54 -0800
Dan Olson via Digitalmars-d <digitalmars-d@puremagic.com> wrote:

> Like D, Java is LTR evaluation for assignment, and I think C# too.  A similar situation to OP code can be created in Java by reassigning an array reference in saveIt().
what i'm talking about is that implicit changing of .ptr is unsafe and error-prone. i *NEVER* explicitly touched '.ptr' in my code, yet somehow it affects me. good compiler should either do what programmer obviously wants it to do (is there somebody who can say that he desperately need the feature in the compiler where compiler modifies stale copy of array data in such code? i doubt), or (and this will be perfectly safe) simply forbid impure assigns for dynamic arrays.

what compiler does now is using it's type system to carefully hide error-prone code. no, this is not "another task for lint". not rejecting such code is "safe" in the terms of "program will not segfault", but it's obviously not safe in terms of "correct code".

using built-in type system not to help me, but to cheat me is something i never expected from D. but now i at least learnt that my "safety" and D "safety" are completely different things. D "safety" is "no segfaults, and let bad code slip in the cracks. and don't try to help programmer, he is smart enough to track it all manually." nonsense with non-uniform function attribures ("@" vs plain), desire to keep prefix "const" as long as possible, strange requiring of utf-8 even in places that aren't compiler deal (shebang), having "0x" and "0b", but ommiting "0o", not allowing 'auto' in foreach... ah, alot of small bits. now i'm starting to see a whole puzzle. it's all about my "safety" and D "safety" are completely different things.

my bad, i chose a wrong language. i'll keep looking for the language that tries to help me writing programs, not cheating me and then blaming me.


« First   ‹ Prev
1 2