2

If I declare an array double x[n] where n is either a constant or an int variable, I can get it's size during runtime. But if I allocate memory using malloc this does not happen. Is this because of stack vs heap memory allocation ? If so how are array sizes for global variables determined and why can't I declare variable length arrays as global variables ? and how does deallocation work since you need to know how much memory to free ?

5
  • 3
    The answer to basically all of your questions is that the memory allocator privately knows how much memory it allocated, but not the type of your object. In fact, it might only know how many blocks of some fixed size it allocated, not necessarily the same as the number of bytes requested. Therefore it does not know how many elements it contains, or even if it's being used as an array or something else. You are expected to keep track of usage-specific information yourself if you need it. The array x in your example has a known type and size at compile time, or inferable at runtime. Commented Jul 13, 2020 at 3:34
  • and also: stackoverflow.com/questions/2650895/… Commented Jul 13, 2020 at 3:35
  • @paddy that would make as good an answer as any. Commented Jul 13, 2020 at 3:35
  • "Is this because of stack vs heap memory allocation ?" --> No. Location irrelevant. Commented Jul 13, 2020 at 9:52
  • "how does deallocation work since you need to know how much memory to free ?" User does not need to keep how much memory there is to free in order to call free(ptr). Commented Jul 13, 2020 at 9:54

2 Answers 2

4

The answer to basically all of your questions is that the memory allocator privately knows how much memory it allocated, but not the type of your object. In fact, it might only know how many blocks of some fixed size it allocated, not necessarily the same as the number of bytes requested. Therefore it does not know how many elements that "array" contains, or even if it's being used as an array at all.

You are expected to keep track of usage-specific information yourself if you need it. You simply request however many bytes you need and then use that memory however you choose. It is not the allocator's responsibility to assist you with this, which gives you full flexibility to do whatever you want.

The array x in your example has a known type and size at compile time, or can be inferred at runtime. In other words, the compiler knows that it should push some number of bytes onto the stack based on the size value and use them as an array of the defined type.

It makes less sense to have VLAs at global scope, since the whole point of the VLA is that it is allocated based on the variable size when entering a block scope. The global scope is only entered once when your program is initialized.

Sign up to request clarification or add additional context in comments.

8 Comments

If I declared x as say double x[10] and make it a global variable I can still use sizeof(x). Global variables are kept in the heap, same as dynamically allocated memory right ? So does the compiler store the size of x somewhere else ?
No, sizeof(x) is constant. The value is known at compile time and hardcoded into your compiled program for any instructions that use the value or other constant derivatives of the value (e.g. sizeof(x) / sizeof(*x) is also constant and is computed at compile time)
Then how does sizeof(x) determine it's value for variable length arrays ?
@moshiur: The compiler invents a local variable which holds that value. Note that the size of x is only known in the scope in which x is declared. If you pass x as an argument to another function, that other function does not know its size.
It doesn't matter where it's stored. The operating system could choose to keep the data segment in a heap if it wants to. This is not your concern unless you're developing OS kernels.
|
0

During translation, the compiler keeps track of all variable definitions and their sizes. Except for VLAs, the sizeof operator is evaluated at compile time, not runtime. How the sizes of VLAs are tracked is up to the individual implementation.

2 Comments

I think what @rici said in the comments is right. Otherwise how would int n; scanf("%i", &n); x[n]; printf("%lu\n", sizeof(x)); work ? So, sizeof can be evaluated at runtime and according to ricci's comment the compiler creates a new variable to track it. Maybe at compile time sizeof is replaced by something like n*sizeof(double) = n*8 ???
@MoshiurRahman: rici’s right that there must be some kind metadata associated with the VLA, but how that’s accomplished is up to each individual implementation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.