4

I had a problem somewhere in my code in a function that I wanted to declare an array but it failed. after some debugging I found out that it uses malloc in disassembly window so I increased the heap size and it works fine!

So my question is why keil uses Heap for local variable?

Here is the variable declaration code:

uint8_t result[data->capacityBytes];
memset(result, 0, sizeof(result));

I've added flag C99

trincot
  • 317,000
  • 35
  • 244
  • 286
Alireza
  • 47
  • 1
  • 7

2 Answers2

6

Your array has a dynamic size, i.e. the compiler does not know how big it will be until runtime. This is a feature introduced in C99 called variable length arrays (VLA).

According to Keil's documentation (see the Note), such arrays are allocated on the heap by this compiler. (Others might allocate on the stack. Others might not implement this feature at all - it became optional in C11.)

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Mat
  • 202,337
  • 40
  • 393
  • 406
  • 1
    Note that there is a very good reason to allocate possibly large structures on the heap rather than on the stack: Stack space is limited, and/or may not grow infinitely quickly. So, allocating a few MiB on the stack at once runs a significantly higher risk of crashing the application than when the array is allocated on the heap. The other side of the medal is, that stack allocations are much faster. – cmaster - reinstate monica Mar 02 '20 at 06:59
  • 1
    The last Keil compiler I used didn't even have a stack for local variables – M.M Mar 02 '20 at 07:17
  • @M.M Is it possible?I've thought that it is the requirement of C language – Alireza Mar 02 '20 at 07:58
  • 1
    @Alireza -- the C Standard doesn't talk about stacks or heaps at all; those concepts belong to implementation details. – ad absurdum Mar 02 '20 at 08:22
  • @Alireza: Some Keil compilers target platforms where a machine-code function that supports recursion would be at least twice as big and slow as one which does not; Keil recognized that a not-quite-conforming compiler which generates efficient code for programs that it accepts would be more useful for many purposes than a conforming compiler that generates horribly inefficient code. – supercat Mar 02 '20 at 22:00
4

Your local variable result is declared the following way:

uint8_t result[data->capacityBytes];

Assuming that data->capacityBytes is not a constant, that would mean that result would be a Variable Length Array (VLA), which would explain the behavior of the compiler you are using.

Then you are assuming that the variable location in memory zone is standardized, which is unfortunately incorrect, as described in this answer:

The C language does not define where any variables are stored, actually. It does, however, define three storage classes: static, automatic, and dynamic.

The location of where variable is stored is up to the interpretation of your source code by the compiler.

See also wikipedia entry about variable length array

Memory

Allocation

dvhh
  • 4,724
  • 27
  • 33
  • 2
    `data->capacityBytes` cannot be a constant, a `const` variable is not a constant, which qualifies for a normal array. `const int a = 5; int b[a];` makes `b` a VLA. – mch Mar 02 '20 at 07:44
  • Is there anyway that I could define the location of such variables? – Alireza Mar 02 '20 at 08:04
  • @Alireza there is an inherent issue with VLA and stack allocation is how do the runtime is suppose to recover from allocation issue, simply crashing would not be an option in most case. Explicit stack alocation is possible via [alloca](http://www.keil.com/support/man/docs/armclang_lib/armclang_lib_chr1359122848123.htm) but does come with its own bag of issues (notably no way to explicitly free allocated memory), uncontrolled stack allocation should be discouraged (if not forbidden in C codebase) – dvhh Mar 02 '20 at 10:03
  • @dvhh: For projects that do not require recursion and do not use VLAs, it is possible to statically validate stack usage. Even for those that do involve recursion, stack usage could be statically validated with the aid of directives to assist in such validation and/or intrinsics to test whether there is sufficient stack to execute code on a "useful" branch, and fall back to a "useless but safe" branch otherwise. Tooling for such things don't seem common, but shouldn't be overly difficult with a little cooperation from compilers. VLAs, however, would massively complicate things. – supercat Mar 15 '20 at 21:00
  • Whether stack allocation is better or worse than heap allocation would depend upon the target platform. On Cortex-M0, the presence of any VLA allocations within a function will degrade the efficiency of accessing automatic objects (not just the VLA!) within the function. – supercat Mar 31 '20 at 20:36