Heap allocation on a microcontrollerPC shares memory with external microcontrollerMicrocontroller on-chip flash consumption - size matters?Interfacing USB with a microcontrollerInductor near the microcontrollerSTM32 Mass Storage with 8K allocation unit sizeSTM Microcontroller burns every timeLinker script and data allocation
What are some examples of three-mora atamadaka verbs besides 帰る?
How to initiate a conversation with a person who recently had transition but you were not in touch with them?
VM with Windows Server won't boot after restoring from ghettoVCB backup
Is there a problem using A LOT of locks in a process?
How do I build a kernel using patches from LKML?
Can I select any of my published paper in journal for book chapter
Using parent's property and will as evidence of assets
Right way to say I disagree with the design but ok I will do
How does the Gameboy Link Cable work?
Chromatic abberation in lens
Impeachment jury tampering
How does an aircraft descend without its nose pointing down?
18-month-old kicked out of church nursery
refreshApex in lwc doesn't seem to work
How to help my son improve without being discouraging?
How can I find the weakness of our "Quality Assurance Process"?
Can only rich people become president?
Electric field due to a hydrogen atom
Continents with simplex noise
How is warfare affected when armor has (temporarily) outpaced guns? How can guns compete?
How did the T-850 still function after it removed its second battery?
Disable the use of the "com.apple.quarantine" extended attribute on Mojave
Gradients - complex shape - Illustrator
Echo bracket symbol to terminal
Heap allocation on a microcontroller
PC shares memory with external microcontrollerMicrocontroller on-chip flash consumption - size matters?Interfacing USB with a microcontrollerInductor near the microcontrollerSTM32 Mass Storage with 8K allocation unit sizeSTM Microcontroller burns every timeLinker script and data allocation
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;
$begingroup$
I'm working on STM32F303VC. How does the heap allocation work?
When I declare the arrays outside main() it allocates them on the heap - SRAM - 0x2000000 and forth in this MCU. But what determines the size of the heap? (And hence its overflow.)
There are two options:
In the 'startup_stm32f30x.s' file I see that:
Heap_Size EQU 0x00000200 // Which is only 1K!
[See here: [http://www.keil.com/support/man/docs/armlib/armlib_chr1358938939461.htm. Anyway, I just used the default file from STM's library]
But on the target configurations options, the R/W memory area is declared to be a size of 0x8000 (which is 32K).
So I checked this in the debugger:
uint16_t _xValH[5000];
uint16_t _xValL[5000];
uint16_t _xVal[5000];
//3*5000*2 bytes each = 30 kilobytes
int main(void)
_xValH[4999] = 0x4;
_xValL[4999] = 0x5;
_xVal[4999] = 0x6;
This didn't throw an exception - which means that it is the second option of the above. But furthermore, even if I go above the 32K - say:
uint16_t _xValH[6000];
uint16_t _xValL[6000];
uint16_t _xVal[6000];
//3*6000*2 bytes each = 36 kilobytes
int main(void)
_xValH[5999] = 0x4;
_xValL[5999] = 0x5;
_xVal[5999] = 0x6;
It's still working! The only time it throws me to exception is when I surpass the 40K - which is the limit of the SRAM (0x20009FFF).
So, what is the meaning of the A line code? And the meaning of the size I enter in B?
stm32 memory
$endgroup$
|
show 1 more comment
$begingroup$
I'm working on STM32F303VC. How does the heap allocation work?
When I declare the arrays outside main() it allocates them on the heap - SRAM - 0x2000000 and forth in this MCU. But what determines the size of the heap? (And hence its overflow.)
There are two options:
In the 'startup_stm32f30x.s' file I see that:
Heap_Size EQU 0x00000200 // Which is only 1K!
[See here: [http://www.keil.com/support/man/docs/armlib/armlib_chr1358938939461.htm. Anyway, I just used the default file from STM's library]
But on the target configurations options, the R/W memory area is declared to be a size of 0x8000 (which is 32K).
So I checked this in the debugger:
uint16_t _xValH[5000];
uint16_t _xValL[5000];
uint16_t _xVal[5000];
//3*5000*2 bytes each = 30 kilobytes
int main(void)
_xValH[4999] = 0x4;
_xValL[4999] = 0x5;
_xVal[4999] = 0x6;
This didn't throw an exception - which means that it is the second option of the above. But furthermore, even if I go above the 32K - say:
uint16_t _xValH[6000];
uint16_t _xValL[6000];
uint16_t _xVal[6000];
//3*6000*2 bytes each = 36 kilobytes
int main(void)
_xValH[5999] = 0x4;
_xValL[5999] = 0x5;
_xVal[5999] = 0x6;
It's still working! The only time it throws me to exception is when I surpass the 40K - which is the limit of the SRAM (0x20009FFF).
So, what is the meaning of the A line code? And the meaning of the size I enter in B?
stm32 memory
$endgroup$
$begingroup$
If you're looking for a runtime exception, keep in mind that not all microcontrollers have them. For example, they will cheerfully do the math to index past the end of a static array (or before the beginning if your math can include negative numbers), access whatever happens to be there, and go on their merry way. Pointers are similarly followed blindly. No memory protection at all, so everything becomes global. | The only exception you might have of any kind could be a hardware interrupt, for which you've presumably written an interrupt service routine, a.k.a. "exception handler" of sorts.
$endgroup$
– AaronD
Jun 7 at 3:31
$begingroup$
In a context like this (powers of two, hexadecimal numbers), it is better to use 1024 for a kilobyte, not 1000.
$endgroup$
– Peter Mortensen
Jun 7 at 8:50
$begingroup$
@AaronD the fact is I do accept exception when supressing the SRAM limit, as I said.
$endgroup$
– Elad
Jun 7 at 12:22
$begingroup$
@Elad On THAT micro, you do, but you don't always have them in the first place. So don't just blindly rely on it. If you start using lower-end hardware, it'll just blindly go after whatever address comes out of the program. If that address is not implemented, it may wrap around (mod RAM_size) and use that address instead, or the write will do nothing and a read will return 0, -1, maybe the address depending on the hardware implementation, or random garbage. In all cases, the program will carry on as if nothing was wrong. What a way to create weird bugs! (peripherals are in that space too...)
$endgroup$
– AaronD
Jun 7 at 17:58
$begingroup$
@AaronD ok, that is an important note. anyway, can you tell me, if so, what is the meaning of the r/w memory area in the 'target configurations' tool on keil? I can see now on keil's site that "The default check box before each entry enables the area globally for the application" - If on practice I can still allocate area on all SRAM, so it doesn't have any meaning de facto. (?)
$endgroup$
– Elad
Jun 10 at 7:46
|
show 1 more comment
$begingroup$
I'm working on STM32F303VC. How does the heap allocation work?
When I declare the arrays outside main() it allocates them on the heap - SRAM - 0x2000000 and forth in this MCU. But what determines the size of the heap? (And hence its overflow.)
There are two options:
In the 'startup_stm32f30x.s' file I see that:
Heap_Size EQU 0x00000200 // Which is only 1K!
[See here: [http://www.keil.com/support/man/docs/armlib/armlib_chr1358938939461.htm. Anyway, I just used the default file from STM's library]
But on the target configurations options, the R/W memory area is declared to be a size of 0x8000 (which is 32K).
So I checked this in the debugger:
uint16_t _xValH[5000];
uint16_t _xValL[5000];
uint16_t _xVal[5000];
//3*5000*2 bytes each = 30 kilobytes
int main(void)
_xValH[4999] = 0x4;
_xValL[4999] = 0x5;
_xVal[4999] = 0x6;
This didn't throw an exception - which means that it is the second option of the above. But furthermore, even if I go above the 32K - say:
uint16_t _xValH[6000];
uint16_t _xValL[6000];
uint16_t _xVal[6000];
//3*6000*2 bytes each = 36 kilobytes
int main(void)
_xValH[5999] = 0x4;
_xValL[5999] = 0x5;
_xVal[5999] = 0x6;
It's still working! The only time it throws me to exception is when I surpass the 40K - which is the limit of the SRAM (0x20009FFF).
So, what is the meaning of the A line code? And the meaning of the size I enter in B?
stm32 memory
$endgroup$
I'm working on STM32F303VC. How does the heap allocation work?
When I declare the arrays outside main() it allocates them on the heap - SRAM - 0x2000000 and forth in this MCU. But what determines the size of the heap? (And hence its overflow.)
There are two options:
In the 'startup_stm32f30x.s' file I see that:
Heap_Size EQU 0x00000200 // Which is only 1K!
[See here: [http://www.keil.com/support/man/docs/armlib/armlib_chr1358938939461.htm. Anyway, I just used the default file from STM's library]
But on the target configurations options, the R/W memory area is declared to be a size of 0x8000 (which is 32K).
So I checked this in the debugger:
uint16_t _xValH[5000];
uint16_t _xValL[5000];
uint16_t _xVal[5000];
//3*5000*2 bytes each = 30 kilobytes
int main(void)
_xValH[4999] = 0x4;
_xValL[4999] = 0x5;
_xVal[4999] = 0x6;
This didn't throw an exception - which means that it is the second option of the above. But furthermore, even if I go above the 32K - say:
uint16_t _xValH[6000];
uint16_t _xValL[6000];
uint16_t _xVal[6000];
//3*6000*2 bytes each = 36 kilobytes
int main(void)
_xValH[5999] = 0x4;
_xValL[5999] = 0x5;
_xVal[5999] = 0x6;
It's still working! The only time it throws me to exception is when I surpass the 40K - which is the limit of the SRAM (0x20009FFF).
So, what is the meaning of the A line code? And the meaning of the size I enter in B?
stm32 memory
stm32 memory
edited Jun 7 at 10:52
Peter Mortensen
1,5743 gold badges14 silver badges22 bronze badges
1,5743 gold badges14 silver badges22 bronze badges
asked Jun 6 at 10:24
EladElad
234 bronze badges
234 bronze badges
$begingroup$
If you're looking for a runtime exception, keep in mind that not all microcontrollers have them. For example, they will cheerfully do the math to index past the end of a static array (or before the beginning if your math can include negative numbers), access whatever happens to be there, and go on their merry way. Pointers are similarly followed blindly. No memory protection at all, so everything becomes global. | The only exception you might have of any kind could be a hardware interrupt, for which you've presumably written an interrupt service routine, a.k.a. "exception handler" of sorts.
$endgroup$
– AaronD
Jun 7 at 3:31
$begingroup$
In a context like this (powers of two, hexadecimal numbers), it is better to use 1024 for a kilobyte, not 1000.
$endgroup$
– Peter Mortensen
Jun 7 at 8:50
$begingroup$
@AaronD the fact is I do accept exception when supressing the SRAM limit, as I said.
$endgroup$
– Elad
Jun 7 at 12:22
$begingroup$
@Elad On THAT micro, you do, but you don't always have them in the first place. So don't just blindly rely on it. If you start using lower-end hardware, it'll just blindly go after whatever address comes out of the program. If that address is not implemented, it may wrap around (mod RAM_size) and use that address instead, or the write will do nothing and a read will return 0, -1, maybe the address depending on the hardware implementation, or random garbage. In all cases, the program will carry on as if nothing was wrong. What a way to create weird bugs! (peripherals are in that space too...)
$endgroup$
– AaronD
Jun 7 at 17:58
$begingroup$
@AaronD ok, that is an important note. anyway, can you tell me, if so, what is the meaning of the r/w memory area in the 'target configurations' tool on keil? I can see now on keil's site that "The default check box before each entry enables the area globally for the application" - If on practice I can still allocate area on all SRAM, so it doesn't have any meaning de facto. (?)
$endgroup$
– Elad
Jun 10 at 7:46
|
show 1 more comment
$begingroup$
If you're looking for a runtime exception, keep in mind that not all microcontrollers have them. For example, they will cheerfully do the math to index past the end of a static array (or before the beginning if your math can include negative numbers), access whatever happens to be there, and go on their merry way. Pointers are similarly followed blindly. No memory protection at all, so everything becomes global. | The only exception you might have of any kind could be a hardware interrupt, for which you've presumably written an interrupt service routine, a.k.a. "exception handler" of sorts.
$endgroup$
– AaronD
Jun 7 at 3:31
$begingroup$
In a context like this (powers of two, hexadecimal numbers), it is better to use 1024 for a kilobyte, not 1000.
$endgroup$
– Peter Mortensen
Jun 7 at 8:50
$begingroup$
@AaronD the fact is I do accept exception when supressing the SRAM limit, as I said.
$endgroup$
– Elad
Jun 7 at 12:22
$begingroup$
@Elad On THAT micro, you do, but you don't always have them in the first place. So don't just blindly rely on it. If you start using lower-end hardware, it'll just blindly go after whatever address comes out of the program. If that address is not implemented, it may wrap around (mod RAM_size) and use that address instead, or the write will do nothing and a read will return 0, -1, maybe the address depending on the hardware implementation, or random garbage. In all cases, the program will carry on as if nothing was wrong. What a way to create weird bugs! (peripherals are in that space too...)
$endgroup$
– AaronD
Jun 7 at 17:58
$begingroup$
@AaronD ok, that is an important note. anyway, can you tell me, if so, what is the meaning of the r/w memory area in the 'target configurations' tool on keil? I can see now on keil's site that "The default check box before each entry enables the area globally for the application" - If on practice I can still allocate area on all SRAM, so it doesn't have any meaning de facto. (?)
$endgroup$
– Elad
Jun 10 at 7:46
$begingroup$
If you're looking for a runtime exception, keep in mind that not all microcontrollers have them. For example, they will cheerfully do the math to index past the end of a static array (or before the beginning if your math can include negative numbers), access whatever happens to be there, and go on their merry way. Pointers are similarly followed blindly. No memory protection at all, so everything becomes global. | The only exception you might have of any kind could be a hardware interrupt, for which you've presumably written an interrupt service routine, a.k.a. "exception handler" of sorts.
$endgroup$
– AaronD
Jun 7 at 3:31
$begingroup$
If you're looking for a runtime exception, keep in mind that not all microcontrollers have them. For example, they will cheerfully do the math to index past the end of a static array (or before the beginning if your math can include negative numbers), access whatever happens to be there, and go on their merry way. Pointers are similarly followed blindly. No memory protection at all, so everything becomes global. | The only exception you might have of any kind could be a hardware interrupt, for which you've presumably written an interrupt service routine, a.k.a. "exception handler" of sorts.
$endgroup$
– AaronD
Jun 7 at 3:31
$begingroup$
In a context like this (powers of two, hexadecimal numbers), it is better to use 1024 for a kilobyte, not 1000.
$endgroup$
– Peter Mortensen
Jun 7 at 8:50
$begingroup$
In a context like this (powers of two, hexadecimal numbers), it is better to use 1024 for a kilobyte, not 1000.
$endgroup$
– Peter Mortensen
Jun 7 at 8:50
$begingroup$
@AaronD the fact is I do accept exception when supressing the SRAM limit, as I said.
$endgroup$
– Elad
Jun 7 at 12:22
$begingroup$
@AaronD the fact is I do accept exception when supressing the SRAM limit, as I said.
$endgroup$
– Elad
Jun 7 at 12:22
$begingroup$
@Elad On THAT micro, you do, but you don't always have them in the first place. So don't just blindly rely on it. If you start using lower-end hardware, it'll just blindly go after whatever address comes out of the program. If that address is not implemented, it may wrap around (mod RAM_size) and use that address instead, or the write will do nothing and a read will return 0, -1, maybe the address depending on the hardware implementation, or random garbage. In all cases, the program will carry on as if nothing was wrong. What a way to create weird bugs! (peripherals are in that space too...)
$endgroup$
– AaronD
Jun 7 at 17:58
$begingroup$
@Elad On THAT micro, you do, but you don't always have them in the first place. So don't just blindly rely on it. If you start using lower-end hardware, it'll just blindly go after whatever address comes out of the program. If that address is not implemented, it may wrap around (mod RAM_size) and use that address instead, or the write will do nothing and a read will return 0, -1, maybe the address depending on the hardware implementation, or random garbage. In all cases, the program will carry on as if nothing was wrong. What a way to create weird bugs! (peripherals are in that space too...)
$endgroup$
– AaronD
Jun 7 at 17:58
$begingroup$
@AaronD ok, that is an important note. anyway, can you tell me, if so, what is the meaning of the r/w memory area in the 'target configurations' tool on keil? I can see now on keil's site that "The default check box before each entry enables the area globally for the application" - If on practice I can still allocate area on all SRAM, so it doesn't have any meaning de facto. (?)
$endgroup$
– Elad
Jun 10 at 7:46
$begingroup$
@AaronD ok, that is an important note. anyway, can you tell me, if so, what is the meaning of the r/w memory area in the 'target configurations' tool on keil? I can see now on keil's site that "The default check box before each entry enables the area globally for the application" - If on practice I can still allocate area on all SRAM, so it doesn't have any meaning de facto. (?)
$endgroup$
– Elad
Jun 10 at 7:46
|
show 1 more comment
5 Answers
5
active
oldest
votes
$begingroup$
You misunderstand what the heap is.
The heap is the area where malloc
gives you blocks of RAM dynamically at run-time.
Your globally scoped, statically allocated variables & arrays are not 'on the heap'.
If you're not using malloc
or any of its variants in your program, you can quite safely set the heap size to 0.
$endgroup$
$begingroup$
Ok, so this explains that it has nothing to do with the heap. Still, what is the meaning of the r/w memory size declared in the target configurations?
$endgroup$
– Elad
Jun 7 at 12:17
add a comment
|
$begingroup$
Those are global variables. Which generally are not allocated on either stack or heap. Exactly where they are is a longer discussion.
Your heap space is for 'globally accessible' variables created during run time. Which is different to global variables, which are allocated before your main() function is entered. Heap space variables can be allocated, de-allocated, reallocated and resized. A global variable you're generally stuck with for the entire program execution.
Your stack space is for local variables. Anything put on it by a function will be removed when the function returns.
While some implementations may put some global variables at the base of the stack, it certainly isn't a rule.
$endgroup$
add a comment
|
$begingroup$
Consider:
uint16_t _xValH[5000];
uint16_t _xValL[5000];
uint16_t _xVal[5000];
//3*5000*2 bytes each = 30Kbytes
int main(void) {
These are global variable declarations. These declarations reserve permanent static space in RAM. The heap is for dynamic allocations in memory.
$endgroup$
add a comment
|
$begingroup$
The Standard does not require freestanding implementations to provide any sort of heap. In some cases, they will pre-allocate a certain amount of space for use by the malloc()
family of functions, with such space being essentially wasted if no such functions are ever used. In other cases, the compiler will reserve a certain amount of RAM for the stack and then make available to malloc()
all storage that isn't and won't be used for any other purpose. In still other cases, an implementation won't provide malloc()
but will provide the starting and ending address of a range of storage that the implementation has been told the hardware has, but which the implementation itself has no use for; a user application may then subdivide this range of addresses via whatever means it sees fit.
In many cases, the latter approach is the best, because user-written allocation functions can offer finer control over allocations and fallback logic than malloc()
. For example, it may be useful to determine, before performing a bunch of allocations, whether all can be guaranteed to succeed (eliminating the need to gracefully recover from an allocation failure in the middle of a task). While malloc()
provides no such flexibility, user-written allocation functions can.
$endgroup$
$begingroup$
"The Standard" can refer to a very large number of documents. Please say which standard you are referring.
$endgroup$
– Stig Hemmer
Jun 7 at 7:38
$begingroup$
The C89, C90, C99, C11, and C17 standards documents, along with their published final drafts, are all consistent on this issue.
$endgroup$
– supercat
Jun 7 at 15:18
add a comment
|
$begingroup$
I hope this should clear things up. It examples the different method of memory allocation in standard C.
#include <stdint.h>
#include <stdlib.h>
#include <stm32f30x.h>
uint32_t static_allocation;
int main(void)
uint32_t stack_allocation;
static uint32_t private_static_allocation;
uint32_t *heap_allocation;
heap_allocation = malloc(4);
static_allocation = 0x11111111;
stack_allocation = 0x22222222;
private_static_allocation = 0x33333333;
*heap_allocation = 0x44444444;
while(1)
// Stop simulation here
__BKPT(0);
// remove not referenced warnings
(void)static_allocation;
(void)stack_allocation;
(void)private_static_allocation;
(void)heap_allocation;
free(heap_allocation);
A quick glimpse at symbol table the ARM Linker generously created shows:
private_static_allocation 0x20000004 Data 4 main.o(.data)
static_allocation 0x20000000 Data 4 main.o(.data)
Which means the linker knows, at compile time, where these variables will live.
Including the following objects in memory map:
0x20000010 0x00000200 Zero RW 2 HEAP startup_stm32f30x.o
0x20000210 0x00000400 Zero RW 1 STACK startup_stm32f30x.o
And to check it really works like this, simulation debugger shows:
Notice stack_allocation
isn't on the actual stack yet, but in a register. This is due to the small amount of variables in this example. Even with -O0
the compiler optimizes stack variables.
Also notice the place of 0x11.., 0x22.. with 0x44.. being inside the heap object.
But no other objects are in here. This means that you can safely reduce heap to 0 if you do not use malloc. Some library functions do implicitly.
Both heap and stack overflow are not warned about during compilation since they are runtime errors.
Relevant documentations: __use_no_heap.
$endgroup$
add a comment
|
Your Answer
StackExchange.ifUsing("editor", function ()
return StackExchange.using("schematics", function ()
StackExchange.schematics.init();
);
, "cicuitlab");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "135"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2felectronics.stackexchange.com%2fquestions%2f442239%2fheap-allocation-on-a-microcontroller%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
You misunderstand what the heap is.
The heap is the area where malloc
gives you blocks of RAM dynamically at run-time.
Your globally scoped, statically allocated variables & arrays are not 'on the heap'.
If you're not using malloc
or any of its variants in your program, you can quite safely set the heap size to 0.
$endgroup$
$begingroup$
Ok, so this explains that it has nothing to do with the heap. Still, what is the meaning of the r/w memory size declared in the target configurations?
$endgroup$
– Elad
Jun 7 at 12:17
add a comment
|
$begingroup$
You misunderstand what the heap is.
The heap is the area where malloc
gives you blocks of RAM dynamically at run-time.
Your globally scoped, statically allocated variables & arrays are not 'on the heap'.
If you're not using malloc
or any of its variants in your program, you can quite safely set the heap size to 0.
$endgroup$
$begingroup$
Ok, so this explains that it has nothing to do with the heap. Still, what is the meaning of the r/w memory size declared in the target configurations?
$endgroup$
– Elad
Jun 7 at 12:17
add a comment
|
$begingroup$
You misunderstand what the heap is.
The heap is the area where malloc
gives you blocks of RAM dynamically at run-time.
Your globally scoped, statically allocated variables & arrays are not 'on the heap'.
If you're not using malloc
or any of its variants in your program, you can quite safely set the heap size to 0.
$endgroup$
You misunderstand what the heap is.
The heap is the area where malloc
gives you blocks of RAM dynamically at run-time.
Your globally scoped, statically allocated variables & arrays are not 'on the heap'.
If you're not using malloc
or any of its variants in your program, you can quite safely set the heap size to 0.
answered Jun 6 at 12:42
brhansbrhans
10.5k2 gold badges25 silver badges33 bronze badges
10.5k2 gold badges25 silver badges33 bronze badges
$begingroup$
Ok, so this explains that it has nothing to do with the heap. Still, what is the meaning of the r/w memory size declared in the target configurations?
$endgroup$
– Elad
Jun 7 at 12:17
add a comment
|
$begingroup$
Ok, so this explains that it has nothing to do with the heap. Still, what is the meaning of the r/w memory size declared in the target configurations?
$endgroup$
– Elad
Jun 7 at 12:17
$begingroup$
Ok, so this explains that it has nothing to do with the heap. Still, what is the meaning of the r/w memory size declared in the target configurations?
$endgroup$
– Elad
Jun 7 at 12:17
$begingroup$
Ok, so this explains that it has nothing to do with the heap. Still, what is the meaning of the r/w memory size declared in the target configurations?
$endgroup$
– Elad
Jun 7 at 12:17
add a comment
|
$begingroup$
Those are global variables. Which generally are not allocated on either stack or heap. Exactly where they are is a longer discussion.
Your heap space is for 'globally accessible' variables created during run time. Which is different to global variables, which are allocated before your main() function is entered. Heap space variables can be allocated, de-allocated, reallocated and resized. A global variable you're generally stuck with for the entire program execution.
Your stack space is for local variables. Anything put on it by a function will be removed when the function returns.
While some implementations may put some global variables at the base of the stack, it certainly isn't a rule.
$endgroup$
add a comment
|
$begingroup$
Those are global variables. Which generally are not allocated on either stack or heap. Exactly where they are is a longer discussion.
Your heap space is for 'globally accessible' variables created during run time. Which is different to global variables, which are allocated before your main() function is entered. Heap space variables can be allocated, de-allocated, reallocated and resized. A global variable you're generally stuck with for the entire program execution.
Your stack space is for local variables. Anything put on it by a function will be removed when the function returns.
While some implementations may put some global variables at the base of the stack, it certainly isn't a rule.
$endgroup$
add a comment
|
$begingroup$
Those are global variables. Which generally are not allocated on either stack or heap. Exactly where they are is a longer discussion.
Your heap space is for 'globally accessible' variables created during run time. Which is different to global variables, which are allocated before your main() function is entered. Heap space variables can be allocated, de-allocated, reallocated and resized. A global variable you're generally stuck with for the entire program execution.
Your stack space is for local variables. Anything put on it by a function will be removed when the function returns.
While some implementations may put some global variables at the base of the stack, it certainly isn't a rule.
$endgroup$
Those are global variables. Which generally are not allocated on either stack or heap. Exactly where they are is a longer discussion.
Your heap space is for 'globally accessible' variables created during run time. Which is different to global variables, which are allocated before your main() function is entered. Heap space variables can be allocated, de-allocated, reallocated and resized. A global variable you're generally stuck with for the entire program execution.
Your stack space is for local variables. Anything put on it by a function will be removed when the function returns.
While some implementations may put some global variables at the base of the stack, it certainly isn't a rule.
answered Jun 6 at 13:13
heketehekete
1,1331 silver badge11 bronze badges
1,1331 silver badge11 bronze badges
add a comment
|
add a comment
|
$begingroup$
Consider:
uint16_t _xValH[5000];
uint16_t _xValL[5000];
uint16_t _xVal[5000];
//3*5000*2 bytes each = 30Kbytes
int main(void) {
These are global variable declarations. These declarations reserve permanent static space in RAM. The heap is for dynamic allocations in memory.
$endgroup$
add a comment
|
$begingroup$
Consider:
uint16_t _xValH[5000];
uint16_t _xValL[5000];
uint16_t _xVal[5000];
//3*5000*2 bytes each = 30Kbytes
int main(void) {
These are global variable declarations. These declarations reserve permanent static space in RAM. The heap is for dynamic allocations in memory.
$endgroup$
add a comment
|
$begingroup$
Consider:
uint16_t _xValH[5000];
uint16_t _xValL[5000];
uint16_t _xVal[5000];
//3*5000*2 bytes each = 30Kbytes
int main(void) {
These are global variable declarations. These declarations reserve permanent static space in RAM. The heap is for dynamic allocations in memory.
$endgroup$
Consider:
uint16_t _xValH[5000];
uint16_t _xValL[5000];
uint16_t _xVal[5000];
//3*5000*2 bytes each = 30Kbytes
int main(void) {
These are global variable declarations. These declarations reserve permanent static space in RAM. The heap is for dynamic allocations in memory.
edited Jun 7 at 10:07
Peter Mortensen
1,5743 gold badges14 silver badges22 bronze badges
1,5743 gold badges14 silver badges22 bronze badges
answered Jun 6 at 23:41
Josko MarsicJosko Marsic
112 bronze badges
112 bronze badges
add a comment
|
add a comment
|
$begingroup$
The Standard does not require freestanding implementations to provide any sort of heap. In some cases, they will pre-allocate a certain amount of space for use by the malloc()
family of functions, with such space being essentially wasted if no such functions are ever used. In other cases, the compiler will reserve a certain amount of RAM for the stack and then make available to malloc()
all storage that isn't and won't be used for any other purpose. In still other cases, an implementation won't provide malloc()
but will provide the starting and ending address of a range of storage that the implementation has been told the hardware has, but which the implementation itself has no use for; a user application may then subdivide this range of addresses via whatever means it sees fit.
In many cases, the latter approach is the best, because user-written allocation functions can offer finer control over allocations and fallback logic than malloc()
. For example, it may be useful to determine, before performing a bunch of allocations, whether all can be guaranteed to succeed (eliminating the need to gracefully recover from an allocation failure in the middle of a task). While malloc()
provides no such flexibility, user-written allocation functions can.
$endgroup$
$begingroup$
"The Standard" can refer to a very large number of documents. Please say which standard you are referring.
$endgroup$
– Stig Hemmer
Jun 7 at 7:38
$begingroup$
The C89, C90, C99, C11, and C17 standards documents, along with their published final drafts, are all consistent on this issue.
$endgroup$
– supercat
Jun 7 at 15:18
add a comment
|
$begingroup$
The Standard does not require freestanding implementations to provide any sort of heap. In some cases, they will pre-allocate a certain amount of space for use by the malloc()
family of functions, with such space being essentially wasted if no such functions are ever used. In other cases, the compiler will reserve a certain amount of RAM for the stack and then make available to malloc()
all storage that isn't and won't be used for any other purpose. In still other cases, an implementation won't provide malloc()
but will provide the starting and ending address of a range of storage that the implementation has been told the hardware has, but which the implementation itself has no use for; a user application may then subdivide this range of addresses via whatever means it sees fit.
In many cases, the latter approach is the best, because user-written allocation functions can offer finer control over allocations and fallback logic than malloc()
. For example, it may be useful to determine, before performing a bunch of allocations, whether all can be guaranteed to succeed (eliminating the need to gracefully recover from an allocation failure in the middle of a task). While malloc()
provides no such flexibility, user-written allocation functions can.
$endgroup$
$begingroup$
"The Standard" can refer to a very large number of documents. Please say which standard you are referring.
$endgroup$
– Stig Hemmer
Jun 7 at 7:38
$begingroup$
The C89, C90, C99, C11, and C17 standards documents, along with their published final drafts, are all consistent on this issue.
$endgroup$
– supercat
Jun 7 at 15:18
add a comment
|
$begingroup$
The Standard does not require freestanding implementations to provide any sort of heap. In some cases, they will pre-allocate a certain amount of space for use by the malloc()
family of functions, with such space being essentially wasted if no such functions are ever used. In other cases, the compiler will reserve a certain amount of RAM for the stack and then make available to malloc()
all storage that isn't and won't be used for any other purpose. In still other cases, an implementation won't provide malloc()
but will provide the starting and ending address of a range of storage that the implementation has been told the hardware has, but which the implementation itself has no use for; a user application may then subdivide this range of addresses via whatever means it sees fit.
In many cases, the latter approach is the best, because user-written allocation functions can offer finer control over allocations and fallback logic than malloc()
. For example, it may be useful to determine, before performing a bunch of allocations, whether all can be guaranteed to succeed (eliminating the need to gracefully recover from an allocation failure in the middle of a task). While malloc()
provides no such flexibility, user-written allocation functions can.
$endgroup$
The Standard does not require freestanding implementations to provide any sort of heap. In some cases, they will pre-allocate a certain amount of space for use by the malloc()
family of functions, with such space being essentially wasted if no such functions are ever used. In other cases, the compiler will reserve a certain amount of RAM for the stack and then make available to malloc()
all storage that isn't and won't be used for any other purpose. In still other cases, an implementation won't provide malloc()
but will provide the starting and ending address of a range of storage that the implementation has been told the hardware has, but which the implementation itself has no use for; a user application may then subdivide this range of addresses via whatever means it sees fit.
In many cases, the latter approach is the best, because user-written allocation functions can offer finer control over allocations and fallback logic than malloc()
. For example, it may be useful to determine, before performing a bunch of allocations, whether all can be guaranteed to succeed (eliminating the need to gracefully recover from an allocation failure in the middle of a task). While malloc()
provides no such flexibility, user-written allocation functions can.
answered Jun 6 at 19:27
supercatsupercat
39.2k1 gold badge66 silver badges115 bronze badges
39.2k1 gold badge66 silver badges115 bronze badges
$begingroup$
"The Standard" can refer to a very large number of documents. Please say which standard you are referring.
$endgroup$
– Stig Hemmer
Jun 7 at 7:38
$begingroup$
The C89, C90, C99, C11, and C17 standards documents, along with their published final drafts, are all consistent on this issue.
$endgroup$
– supercat
Jun 7 at 15:18
add a comment
|
$begingroup$
"The Standard" can refer to a very large number of documents. Please say which standard you are referring.
$endgroup$
– Stig Hemmer
Jun 7 at 7:38
$begingroup$
The C89, C90, C99, C11, and C17 standards documents, along with their published final drafts, are all consistent on this issue.
$endgroup$
– supercat
Jun 7 at 15:18
$begingroup$
"The Standard" can refer to a very large number of documents. Please say which standard you are referring.
$endgroup$
– Stig Hemmer
Jun 7 at 7:38
$begingroup$
"The Standard" can refer to a very large number of documents. Please say which standard you are referring.
$endgroup$
– Stig Hemmer
Jun 7 at 7:38
$begingroup$
The C89, C90, C99, C11, and C17 standards documents, along with their published final drafts, are all consistent on this issue.
$endgroup$
– supercat
Jun 7 at 15:18
$begingroup$
The C89, C90, C99, C11, and C17 standards documents, along with their published final drafts, are all consistent on this issue.
$endgroup$
– supercat
Jun 7 at 15:18
add a comment
|
$begingroup$
I hope this should clear things up. It examples the different method of memory allocation in standard C.
#include <stdint.h>
#include <stdlib.h>
#include <stm32f30x.h>
uint32_t static_allocation;
int main(void)
uint32_t stack_allocation;
static uint32_t private_static_allocation;
uint32_t *heap_allocation;
heap_allocation = malloc(4);
static_allocation = 0x11111111;
stack_allocation = 0x22222222;
private_static_allocation = 0x33333333;
*heap_allocation = 0x44444444;
while(1)
// Stop simulation here
__BKPT(0);
// remove not referenced warnings
(void)static_allocation;
(void)stack_allocation;
(void)private_static_allocation;
(void)heap_allocation;
free(heap_allocation);
A quick glimpse at symbol table the ARM Linker generously created shows:
private_static_allocation 0x20000004 Data 4 main.o(.data)
static_allocation 0x20000000 Data 4 main.o(.data)
Which means the linker knows, at compile time, where these variables will live.
Including the following objects in memory map:
0x20000010 0x00000200 Zero RW 2 HEAP startup_stm32f30x.o
0x20000210 0x00000400 Zero RW 1 STACK startup_stm32f30x.o
And to check it really works like this, simulation debugger shows:
Notice stack_allocation
isn't on the actual stack yet, but in a register. This is due to the small amount of variables in this example. Even with -O0
the compiler optimizes stack variables.
Also notice the place of 0x11.., 0x22.. with 0x44.. being inside the heap object.
But no other objects are in here. This means that you can safely reduce heap to 0 if you do not use malloc. Some library functions do implicitly.
Both heap and stack overflow are not warned about during compilation since they are runtime errors.
Relevant documentations: __use_no_heap.
$endgroup$
add a comment
|
$begingroup$
I hope this should clear things up. It examples the different method of memory allocation in standard C.
#include <stdint.h>
#include <stdlib.h>
#include <stm32f30x.h>
uint32_t static_allocation;
int main(void)
uint32_t stack_allocation;
static uint32_t private_static_allocation;
uint32_t *heap_allocation;
heap_allocation = malloc(4);
static_allocation = 0x11111111;
stack_allocation = 0x22222222;
private_static_allocation = 0x33333333;
*heap_allocation = 0x44444444;
while(1)
// Stop simulation here
__BKPT(0);
// remove not referenced warnings
(void)static_allocation;
(void)stack_allocation;
(void)private_static_allocation;
(void)heap_allocation;
free(heap_allocation);
A quick glimpse at symbol table the ARM Linker generously created shows:
private_static_allocation 0x20000004 Data 4 main.o(.data)
static_allocation 0x20000000 Data 4 main.o(.data)
Which means the linker knows, at compile time, where these variables will live.
Including the following objects in memory map:
0x20000010 0x00000200 Zero RW 2 HEAP startup_stm32f30x.o
0x20000210 0x00000400 Zero RW 1 STACK startup_stm32f30x.o
And to check it really works like this, simulation debugger shows:
Notice stack_allocation
isn't on the actual stack yet, but in a register. This is due to the small amount of variables in this example. Even with -O0
the compiler optimizes stack variables.
Also notice the place of 0x11.., 0x22.. with 0x44.. being inside the heap object.
But no other objects are in here. This means that you can safely reduce heap to 0 if you do not use malloc. Some library functions do implicitly.
Both heap and stack overflow are not warned about during compilation since they are runtime errors.
Relevant documentations: __use_no_heap.
$endgroup$
add a comment
|
$begingroup$
I hope this should clear things up. It examples the different method of memory allocation in standard C.
#include <stdint.h>
#include <stdlib.h>
#include <stm32f30x.h>
uint32_t static_allocation;
int main(void)
uint32_t stack_allocation;
static uint32_t private_static_allocation;
uint32_t *heap_allocation;
heap_allocation = malloc(4);
static_allocation = 0x11111111;
stack_allocation = 0x22222222;
private_static_allocation = 0x33333333;
*heap_allocation = 0x44444444;
while(1)
// Stop simulation here
__BKPT(0);
// remove not referenced warnings
(void)static_allocation;
(void)stack_allocation;
(void)private_static_allocation;
(void)heap_allocation;
free(heap_allocation);
A quick glimpse at symbol table the ARM Linker generously created shows:
private_static_allocation 0x20000004 Data 4 main.o(.data)
static_allocation 0x20000000 Data 4 main.o(.data)
Which means the linker knows, at compile time, where these variables will live.
Including the following objects in memory map:
0x20000010 0x00000200 Zero RW 2 HEAP startup_stm32f30x.o
0x20000210 0x00000400 Zero RW 1 STACK startup_stm32f30x.o
And to check it really works like this, simulation debugger shows:
Notice stack_allocation
isn't on the actual stack yet, but in a register. This is due to the small amount of variables in this example. Even with -O0
the compiler optimizes stack variables.
Also notice the place of 0x11.., 0x22.. with 0x44.. being inside the heap object.
But no other objects are in here. This means that you can safely reduce heap to 0 if you do not use malloc. Some library functions do implicitly.
Both heap and stack overflow are not warned about during compilation since they are runtime errors.
Relevant documentations: __use_no_heap.
$endgroup$
I hope this should clear things up. It examples the different method of memory allocation in standard C.
#include <stdint.h>
#include <stdlib.h>
#include <stm32f30x.h>
uint32_t static_allocation;
int main(void)
uint32_t stack_allocation;
static uint32_t private_static_allocation;
uint32_t *heap_allocation;
heap_allocation = malloc(4);
static_allocation = 0x11111111;
stack_allocation = 0x22222222;
private_static_allocation = 0x33333333;
*heap_allocation = 0x44444444;
while(1)
// Stop simulation here
__BKPT(0);
// remove not referenced warnings
(void)static_allocation;
(void)stack_allocation;
(void)private_static_allocation;
(void)heap_allocation;
free(heap_allocation);
A quick glimpse at symbol table the ARM Linker generously created shows:
private_static_allocation 0x20000004 Data 4 main.o(.data)
static_allocation 0x20000000 Data 4 main.o(.data)
Which means the linker knows, at compile time, where these variables will live.
Including the following objects in memory map:
0x20000010 0x00000200 Zero RW 2 HEAP startup_stm32f30x.o
0x20000210 0x00000400 Zero RW 1 STACK startup_stm32f30x.o
And to check it really works like this, simulation debugger shows:
Notice stack_allocation
isn't on the actual stack yet, but in a register. This is due to the small amount of variables in this example. Even with -O0
the compiler optimizes stack variables.
Also notice the place of 0x11.., 0x22.. with 0x44.. being inside the heap object.
But no other objects are in here. This means that you can safely reduce heap to 0 if you do not use malloc. Some library functions do implicitly.
Both heap and stack overflow are not warned about during compilation since they are runtime errors.
Relevant documentations: __use_no_heap.
edited Jun 7 at 12:16
answered Jun 7 at 12:10
Jeroen3Jeroen3
14.3k20 silver badges54 bronze badges
14.3k20 silver badges54 bronze badges
add a comment
|
add a comment
|
Thanks for contributing an answer to Electrical Engineering Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2felectronics.stackexchange.com%2fquestions%2f442239%2fheap-allocation-on-a-microcontroller%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
$begingroup$
If you're looking for a runtime exception, keep in mind that not all microcontrollers have them. For example, they will cheerfully do the math to index past the end of a static array (or before the beginning if your math can include negative numbers), access whatever happens to be there, and go on their merry way. Pointers are similarly followed blindly. No memory protection at all, so everything becomes global. | The only exception you might have of any kind could be a hardware interrupt, for which you've presumably written an interrupt service routine, a.k.a. "exception handler" of sorts.
$endgroup$
– AaronD
Jun 7 at 3:31
$begingroup$
In a context like this (powers of two, hexadecimal numbers), it is better to use 1024 for a kilobyte, not 1000.
$endgroup$
– Peter Mortensen
Jun 7 at 8:50
$begingroup$
@AaronD the fact is I do accept exception when supressing the SRAM limit, as I said.
$endgroup$
– Elad
Jun 7 at 12:22
$begingroup$
@Elad On THAT micro, you do, but you don't always have them in the first place. So don't just blindly rely on it. If you start using lower-end hardware, it'll just blindly go after whatever address comes out of the program. If that address is not implemented, it may wrap around (mod RAM_size) and use that address instead, or the write will do nothing and a read will return 0, -1, maybe the address depending on the hardware implementation, or random garbage. In all cases, the program will carry on as if nothing was wrong. What a way to create weird bugs! (peripherals are in that space too...)
$endgroup$
– AaronD
Jun 7 at 17:58
$begingroup$
@AaronD ok, that is an important note. anyway, can you tell me, if so, what is the meaning of the r/w memory area in the 'target configurations' tool on keil? I can see now on keil's site that "The default check box before each entry enables the area globally for the application" - If on practice I can still allocate area on all SRAM, so it doesn't have any meaning de facto. (?)
$endgroup$
– Elad
Jun 10 at 7:46