static array internal & dangling reference

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Nov 13 22:10:38 PST 2016


On Monday, November 14, 2016 05:53:04 Picaud Vincent via Digitalmars-d-learn 
wrote:
> On Sunday, 13 November 2016 at 23:39:37 UTC, Steven Schveighoffer
>
> wrote:
> > Note that he is declaring an int[10] inside the function and
> > then returning it. The compiler must see that the int[10] will
> > be returned, and so it reuses the pre-allocated buffer for
> > returning as the same address to avoid copying.
> >
> > I would guess it's probably fine, with no dangling reference.
>
> Thank you for your comment.
>
> On my side there is still something mysterious. I one case:
>
> int[] f()
> {
>    int[10] sa;
>    foreach(int i, ref sa_i;sa){
>      sa_i=i;
>    }
>    int[] sb=sa;
>    return sb;
> }
>
> void f_test()
> {
>    auto sb=f();
>    sb[2]=100;     // Valgrind ok
> }
>
> Valgrind does not complain.
>
> But on the other case:
>
> // same int[] f() function
>
> void f_test() {
>      auto sb=f();
>      sb[2] = 100;
>      writeln(sb[2]);
>      int test[100];  // these two lines make Valgrind panicking
>      writeln(sb[2]); //
> }
>
> it complains with "Conditional jump or move depends on
> uninitialised value(s)"
>
>
> I think my two examples are creating a dangling pointer. But I
> would be happy to understand why Valgrind is not complaining for
> the first one.

I would have hoped that it would have complained about the first one. I
don't know why it isn't. It definitely results in having a pointer to memory
that should no longer be referenced. In the second case though, it probably
complains because by declaring the static array test, there is now a static
array which presumably uses some of the same memory that now destroyed
static array from the call to f used. But I don't know exactly what valgrind
looks at and how it makes such decisions. Regardless, there's no question
that returning a dynamic array which is a slice of a static array is not
something that is valid to do when that static array is a local variable.
Valgrind just isn't managing to catch it in this case, unfortunately.

Hmm. Thinking on this further, it _might_ be that the

sb[2] = 100;

line is not flagged, because at that point, sb.ptr might actually be
referring to memory inside of the dynamic array reference - i.e. the struct
that looks something like

struct DynamicArray(T)
{
    size_t length;
    T* ptr;
}

since it would probably sit on the stack in roughly the same place that the
static array had been inside of f. And if that's the case, then sb[2] is
probably within the data that the dynamic array has on the stack, in which
case, from valgrind's perspective, it's memory that is legitimate to access.
If you tried accessing an element that would be beyond the size of the data
that the dynamic array has on the stack, then maybe valgrind would flag
that. I don't know. I'm just guessing, and I can't properly test it on the
box that I'm typing from at the moment.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list