0

(First of all : This code is intented to run only on Windows10 but behavior on other OS is interesting. Of course, change _msize by the appropriate function)

Part I of the code. Memory allocation is done with malloc and I use _msize to print the element number of an array in a function (I know that, for memory allocation reason ..., I could have a superior value but I have not yet observed such a case. If you have real case where it happens, I am interested but it is not the main reason of my question )

Part II of the code : Same idea but with variable lenght array. I have two questions. First, is there an equivalent of _msize for VLA ? and second, my program hangs, why does not _msize return ?

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

void myfoo(int *array) {
    printf("Nb elt of an array obtained from its pointer %d\n",_msize(array)/sizeof(int));
}

int main() {
    int n=1;

    printf("Part 1 : malloc\n");
    while(n>0) {
        printf("n : ");scanf("%d",&n);
        if (n<0) break;
        int *array;
        array=malloc(n*sizeof(int));
        for (int i=0;i<n;i++) {array[i]=i;}
        myfoo(array);
        free(array);
    }

    n=1;
    printf("Part 1I : Variable Length Array\n");
    while(n>0) {
        printf("n : ");scanf("%d",&n);
        if (n<0) break;
        int array[n];
        for (int i=0;i<n;i++) {array[i]=i;}
        myfoo(array);
    }
}
Stef1611
  • 1,978
  • 2
  • 11
  • 30
  • 2
    The documentation of `_msize` clearly specifies it expects a pointer returned by `malloc`, `calloc` or `realloc`. A VLA is non of those. You should pay closer attention to a function's documented contract. – StoryTeller - Unslander Monica Jan 09 '19 at 09:14
  • @storyteller. OK, I agree with you and I am not surprised that _msize does not work. VLA memory allocation is on the stack and malloc memory allocation on the heap. My first question is "is there an equivalent of _msize for VLA ?" and, concerning the second one, I was expected an answer from a technical point of view. For example : `int aaa; printf("%d\n",_msize(aaa));` returns -1 and the program does not hang. – Stef1611 Jan 09 '19 at 09:30
  • @storyteller. Following your remark, I edit the title. – Stef1611 Jan 09 '19 at 10:01
  • 2
    A function such as `_msize()` that requires a pointer to memory allocated on the heap can't be safely used unless you have some way of knowing that the random `foo *` pointer you get actually references a heap object. Your `void myfoo(int *array)` can be passed an `int *` that refers to `int` value(s) *anywhere*. To use something like `_msize()`, you'd have to carry around a "this is a pointer to heap memory" bit of data around with the pointer. Once you have to do that, you might as well just carry around the size of the memory along with the pointer and be able to use it on any pointer type. – Andrew Henle Jan 09 '19 at 10:19
  • 2
    (cont) *"is there an equivalent of _msize for VLA ?"* If there were, it would only be useful on VLAs - and would again need a flag carried around with the pointer to say "this is a VLA" when you pass it to a function. Again - just pass the size if you need it. That's just the way C works - it started as a low-level language, and it has kept many vestiges of that. One of those is that arrays decay to pointers when passed to functions, and the length of the array is lost. – Andrew Henle Jan 09 '19 at 10:23
  • 1
    So, IMO `_msize()` is actually anything but great - it's downright horrible. Using it plants a land mine in your code - your code works for a long time, then someone makes a change that passes a static array or VLA to it and your code blows up and fails. Not only is `_msize()` a failure-waiting-to-happen, it an proprietary extension that needlessly makes your code non-portable. – Andrew Henle Jan 09 '19 at 10:33
  • @AndrewHenle. Thanks a lot for all of your answers.Is malloc_usable_size (the equivalent of _msize on linux) more secure or is it the same ? If you have time, could read my comments to Jose (see the answer) about the sizeof operator on VLA. I read many documents on the net (array name is not a pointer, what &array is ?, sizeof is an operator, array decays to a pointer, difference between &array, array, *array, array[0], ...). If sizeof could evaluate the size, with the ptr that decays from arrayname, is it possible to look for this value in a table and get the size of the array. – Stef1611 Jan 09 '19 at 11:01
  • @AndrewHenle. In the last comment, with table, I mean some kind of structure that describe the stack and that I suppose, it is used by sizeof. – Stef1611 Jan 09 '19 at 11:04
  • @Stef1611 *some kind of structure that describe the stack and that I suppose, it is used by sizeof* No, because `sizeof()` can only work on a VLA in the scope the VLA is created - the compiler will be able to return the size of the array by any means it wants to. Once you pass a VLA to another function, that context is lost and it's just a pointer. Again, there's no way to safely use such functions as `malloc_usable_size()` or `_msize()` or you hypothetical `get_VLA_size()` without also passing the type of array. And once you have to pass the type, you might as well just pass the size. – Andrew Henle Jan 10 '19 at 12:19

1 Answers1

0

A VLA (on the stack) is not the expected value by _msize, given that the expected bunch of memory is from the heap which has been allocated by a dynamic allocator:

[...Returns the size of a memory block allocated in the heap. ...]

[... The _msize function returns the size, in bytes, of the memory block allocated by a call to calloc, malloc, or realloc. ...]

That is the reason why the first part of the code should work as expected, but not the second one.

For the completeness sake, when you pass an array, it decays to a pointer, so the function is getting just a pointer. So the function should receive the number of elements in the array too (besides of the pointer). See this: Passing a multidimensional variable length array to a function

Community
  • 1
  • 1
Jose
  • 3,306
  • 1
  • 17
  • 22
  • I agree please read my comment to storyteller. And concerning the array that decays to a pointer I am aware of that (a long story : https://stackoverflow.com/questions/54073251/variable-declaration-in-function-prototype-and-in-block-code-difference) – Stef1611 Jan 09 '19 at 09:37
  • Therefore, I should conclude that it is impossible to know the size of a VLA only from its pointer information. So, the following question, how is it possible with the operator sizeof ? Which supplementary information could be obtained with the array name that it is lost when it decays to a pointer ? – Stef1611 Jan 09 '19 at 09:55
  • You are not able to get the size of an array with just a pointer. In the same way that you are not able to know the size of an array with just the first element (or can you know the number of elements in `array` based on `array[0]`?). As I said, you have to pass the number of elements too. – Jose Jan 09 '19 at 10:02
  • This is what I do in all my program and for a few days I use structure { int size, int array[]} and flexible array member. But I would like to understand much more subtilities. So, the question in my last comment, how is it possible with the operator sizeof ? Which supplementary information could be obtained with the array name that it is lost when it decays to a pointer ? – Stef1611 Jan 09 '19 at 10:11
  • Thanks for your comment on accept. I am new in stackoverflow (I subscribed for a long time but I did not use it often and I had no answer on my first questions) so I voted up for interesting and helpful answers but I did not accept them. To be perfectly honest, I did not really see the difference. Now, it is clear. (When you have read this comment, let me know, I will remove it because it is not really a comment and I do not know how to write you directly) – Stef1611 Jan 09 '19 at 10:23