Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #76708

Re: sizeof on an uninitialized pointer to a VLA

From Keith Thompson <kst-u@mib.org>
Newsgroups comp.lang.c
Subject Re: sizeof on an uninitialized pointer to a VLA
Date 2015-11-20 18:29 -0800
Organization None to speak of
Message-ID <lnsi40axv9.fsf@kst-u.example.com> (permalink)
References <5e03af2c-3c3e-4432-bf5a-000867e5febb@googlegroups.com> <n2ljik$iqo$1@dont-email.me> <ln610wevm8.fsf@kst-u.example.com> <87mvu8rbor.fsf@bsb.me.uk>

Show all headers | View raw


Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> Keith Thompson <kst-u@mib.org> writes:
>> James Kuyper <jameskuyper@verizon.net> writes:
>>> On 11/19/2015 02:39 PM, John Bode wrote:
>>>> I've been using the following idiom a lot to dynamically allocate
>>>> 2D arrays:
>>>> 
>>>>     T (*arr)[N] = malloc( sizeof *arr * M );
>>>
>>> M=>N?
>>>
>>>> Works great where N is known at compile time.  However, I've also been
>>>> applying it to VLAs, like so:
>>>> 
>>>>     size_t rows;
>>>>     size_t cols;
>>>>     ...
>>>>     T (*arr)[rows] = malloc( sizeof *arr * cols );
>>>> 
>>>> I've never had any issues, but...does this count as undefined behavior?  
>>>> `sizeof` evaluates the operand when it's a VLA, but what does "evaluate"
>>>> mean in this context?  Is it trying to dereference the pointer, or is it
>>>> simply determining the size of *any* object the pointer may refer to?  
>>>
>>> The key thing about VLA types is that their sized depends upon the value
>>> of one or more expressions, in this case the relevant expression is
>>> "rows". The evaluation it's talking about is the evaluation of that
>>> expression. Unless the expression has side-effects (for example,
>>> rows++), the possibility of it being evaluated is not an issue you need
>>> to worry about.
>>
>> No, the expression `rows` is not evaluated.
>>
>> Consider:
>>
>>     size_t rows = 10;
>>     char vla[rows];
>>     rows = 20;
>>     sizeof vla;
>>
>> `sizeof vla` is 10, not 20.  Evaluating `rows` is not just
>> unnecessary; it gives the wrong result.
>>
>> I think the standard is just being sloppy to the point of being
>> incorrect here.  For non-VLA types, `sizeof expr` and `sizeof
>> (typename)` are evaluated at compile time.
>
> I agree that the wording probably does not say what was intended.
> Unfortunately it's not really unclear so what should a conforming
> compiler do?
>>
>> For an expression of a VLA type, `sizeof expr` has to be determined
>> at run time, but the only thing that actually needs to be evaluated
>> is the stored value of whatever anonymous object the compiler
>> uses to remember the size (with perhaps some other computation if,
>> for example, the stored value is an element count).  Neither the
>> expression that determined the size (whose value may not be the same)
>> nor the value of the array object (which consists of the values of
>> its elements) actually needs to be evaluated.
>>
>> For `sizeof` applied to a parenthesized VLA type, any expressions
>> that are part of the type name have to be evaluated.  For example,
>> in `sizeof (char[func()])`, the function has to be called and any
>> side effects must occur; similarly for `sizeof (char[n++])`.
>
> But, as I am sure you know, the wording in the standard goes further.
> If we replace *arr with arr[0] but with the 0 being produced by a
> function call:
>
>   sizeof arr[f()]
>
> then the wording says that f must be called.  gcc obliges but clang does
> not.  (No implementation is required to go any further and actually
> access the as yet non-existent array, but the standard, as worded,
> implies that the above, and the original, are undefined.)

Interesting point.  Here's an example:

    #include <stdio.h>

    int zero(void) {
        puts("zero()");
        return 0;
    }

    int main(void) {
        int n = 10;
        char vla[n][n];
        printf("sizeof vla[zero()] = %zu\n", sizeof vla[zero()]);
    }

The output using every version of gcc and clang I've tried is:

    zero()
    sizeof vla[zero()] = 10

The sizeof computation is correct, but it *could* have been determined
without calling the function.  As far as I can tell, the value returned
by the call to zero() can have no effect on the result of the sizeof
computation.

>> The standard doesn't actually manage to say all this, but I think
>> that's the only reasonable interpretation of the intent.
>
> As you say, the intent may well have been to limit evaluation to
> expressions contained in type names of VLAs, but it certainly doesn't
> say that, and at least one implementation has taken the literal meaning.
>
> Maybe rather than this:
>
>   "If the type of the operand is a variable length array type, the
>   operand is evaluated; otherwise, the operand is not evaluated and the
>   result is an integer constant."
>
> what was meant was this:
>
>   "If the operand is a variable length array type name, any expressions
>   in the operand are evaluated; otherwise, the operand is not evaluated
>   and the result is an integer constant."

The result of `sizeof vla_object` is not an integer constant.  (Aside:
"integer constant" is a poor choice of words, since that phrase has a
different meaning.)

The type of the operand to sizeof is known at compile time, and
I believe that the size of that type can always be determined
without evaluating anything other than the values of anonymous
compiler-generated objects (or whatever mechanism the implementation
uses to remember the size of a VLA type).

I suggest something like:

    If the operand is a parenthesized variable length array type name,
    any expressions in the operand are evaluated.  Otherwise, the
    operand is not evaluated.  The result is constant unless the
    type of the operand is a variable length array type.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

Back to comp.lang.c | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

sizeof on an uninitialized pointer to a VLA John Bode <jfbode1029@gmail.com> - 2015-11-19 11:39 -0800
  Re: sizeof on an uninitialized pointer to a VLA supercat@casperkitty.com - 2015-11-19 12:09 -0800
  Re: sizeof on an uninitialized pointer to a VLA "A. Bolmarcich" <aggedor@earl-grey.cloud9.net> - 2015-11-19 21:40 +0000
    Re: sizeof on an uninitialized pointer to a VLA supercat@casperkitty.com - 2015-11-19 13:50 -0800
  Re: sizeof on an uninitialized pointer to a VLA James Kuyper <jameskuyper@verizon.net> - 2015-11-19 17:50 -0500
    Re: sizeof on an uninitialized pointer to a VLA supercat@casperkitty.com - 2015-11-19 15:31 -0800
    Re: sizeof on an uninitialized pointer to a VLA Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-20 01:09 +0000
      Re: sizeof on an uninitialized pointer to a VLA supercat@casperkitty.com - 2015-11-19 19:10 -0800
    Re: sizeof on an uninitialized pointer to a VLA Keith Thompson <kst-u@mib.org> - 2015-11-20 03:52 -0800
      Re: sizeof on an uninitialized pointer to a VLA Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-20 14:24 +0000
        Re: sizeof on an uninitialized pointer to a VLA supercat@casperkitty.com - 2015-11-20 10:25 -0800
        Re: sizeof on an uninitialized pointer to a VLA Keith Thompson <kst-u@mib.org> - 2015-11-20 18:29 -0800
          Re: sizeof on an uninitialized pointer to a VLA Ian Collins <ian-news@hotmail.com> - 2015-11-21 16:35 +1300
            Re: sizeof on an uninitialized pointer to a VLA Keith Thompson <kst-u@mib.org> - 2015-11-20 20:24 -0800
              Re: sizeof on an uninitialized pointer to a VLA Ian Collins <ian-news@hotmail.com> - 2015-11-21 17:38 +1300
                Re: sizeof on an uninitialized pointer to a VLA Keith Thompson <kst-u@mib.org> - 2015-11-20 21:08 -0800
          Re: sizeof on an uninitialized pointer to a VLA Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-21 10:46 +0000
            Re: sizeof on an uninitialized pointer to a VLA Keith Thompson <kst-u@mib.org> - 2015-11-21 03:26 -0800
              Re: sizeof on an uninitialized pointer to a VLA Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-21 12:46 +0000
                Re: sizeof on an uninitialized pointer to a VLA Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-21 14:01 +0000
              Re: sizeof on an uninitialized pointer to a VLA supercat@casperkitty.com - 2015-11-21 09:02 -0800
                Re: sizeof on an uninitialized pointer to a VLA Keith Thompson <kst-u@mib.org> - 2015-11-21 12:09 -0800

csiph-web