다른 답변 외에도 스택과 힙 공간 사이에 RAM을 조각 할 때 정적이 아닌 정적 데이터 (예 : 파일 전역, 함수 정적 및 프로그램 전체)를위한 공간을 고려해야한다고 덧붙이고 싶습니다. C 관점에서 글로벌, 아마도 C ++에서 다른 것).
스택 / 힙 할당 작동 방식
시작 어셈블리 파일이 영역을 정의하는 한 가지 방법이라는 점은 주목할 가치가 있습니다. 툴체인 (빌드 환경 및 런타임 환경 모두)은 스택 공간의 시작 (벡터 테이블에 초기 스택 포인터를 저장하는 데 사용됨) 및 힙 공간의 시작 및 끝 (동적에 의해 사용됨)을 정의하는 기호를 주로 관리합니다. 일반적으로 libc에서 제공하는 메모리 할당 자)
OP의 예에서는 1kiB의 스택 크기와 0B의 힙 크기라는 두 개의 심볼 만 정의됩니다. 이 값은 실제로 스택 및 힙 공간을 생성하기 위해 다른 곳에서 사용됩니다.
@Gilles 예제에서, 크기는 어셈블리 파일에서 정의 되어 사용 되어 어디에서나 크기를 유지하는 스택 공간을 설정합니다. Stack_Mem 기호로 식별되고 끝에 __initial_sp 레이블을 설정합니다. 공간이 Heap_Mem (0.5kiB 크기)이지만 시작과 끝에 레이블 (__heap_base 및 __heap_limit)이있는 힙의 경우에도 마찬가지입니다.
이들은 링커에 의해 처리되며, 스택 공간과 힙 공간 내에서 메모리가 점유되어 있기 때문에 스택 공간과 힙 공간 내에 아무것도 할당하지 않지만 필요한 경우 메모리와 모든 전역을 배치 할 수 있습니다. 레이블은 주어진 주소에서 길이가없는 기호입니다. __initial_sp는 링크 타임에 벡터 테이블에 직접 사용되며 런타임 코드에 따라 __heap_base 및 __heap_limit가 사용됩니다. 심볼의 실제 주소는 위치에 따라 링커에서 할당합니다.
위에서 언급했듯이 이러한 기호는 실제로 startup.s 파일에서 가져 오지 않아도됩니다. 링커 구성 (Keil의 스 캐터로드 파일, GNU의 링커 스크립트) 및 배치에 대한 세밀한 제어가 가능합니다. 예를 들어 스택을 RAM의 시작 또는 끝에 강제로 두거나 전역을 힙이나 원하는 곳에 두지 않도록 할 수 있습니다. 전역을 배치 한 후 남은 RAM을 HEAP 또는 STACK 만 차지하도록 지정할 수도 있습니다. 그러나 다른 메모리가 줄어드는 정적 변수를 더 추가하면주의해야합니다.
그러나 각 툴체인은 다르며 구성 파일을 작성하는 방법과 동적 메모리 할당자가 사용할 기호는 특정 환경의 문서에서 가져와야합니다.
스택 크기
스택 크기를 결정하는 방법에 대해서는 재귀 나 함수 포인터를 사용하지 않는 경우 많은 툴체인이 프로그램의 함수 호출 트리를 분석하여 최대 스택 깊이를 제공 할 수 있습니다. 이를 사용하는 경우 스택 크기를 추정하고 기본 값 (아마도 main 이전의 입력 기능을 통해)으로 미리 채운 다음 최대 깊이가있는 곳 (기본 값이있는 위치) 동안 프로그램을 실행 한 후 확인 종료). 프로그램을 한계까지 완전히 연습 한 경우 스택을 축소 할 수 있는지 또는 프로그램이 충돌하거나 기본 값이 남아 있지 않은 경우 스택을 늘리고 다시 시도해야하는지 상당히 정확하게 알 수 있습니다.
힙 사이징
힙 크기를 결정하는 것은 응용 프로그램에 따라 조금 더 다릅니다. 시작하는 동안 동적 할당 만 수행하는 경우 시작 코드에 필요한 공간을 추가하고 메모리 관리를위한 오버 헤드를 추가 할 수 있습니다. 메모리 관리자의 소스에 액세스 할 수 있으면 오버 헤드가 무엇인지 정확히 알 수 있으며 메모리를 사용하여 사용 정보를 제공하는 코드를 작성할 수도 있습니다. 동적 런타임 메모리 (예 : 인바운드 이더넷 프레임에 버퍼 할당)가 필요한 응용 프로그램의 경우 스택 크기를 신중하게 연마하고 스택 및 정적 후에 남은 모든 것을 힙에 제공하는 것이 좋습니다.
최종 메모 (RTOS)
OP의 질문은 베어 메탈 태그로 지정되었지만 RTOS에 메모를 추가하고 싶습니다. 종종 (항상?) 각 작업 / 프로세스 / 스레드 (간단히하기 위해 여기에 작업을 작성하겠습니다)에는 작업이 생성 될 때 스택 크기가 할당됩니다. 작업 스택 외에도 작은 OS가있을 것입니다 스택 (인터럽트 등에 사용)
작업 회계 구조와 스택은 어딘가에서 할당되어야하며, 이는 종종 애플리케이션의 전체 힙 공간에서 발생합니다. 이러한 경우 초기 스택 크기는 중요하지 않습니다. OS는 초기화 중에 만 스택을 사용하기 때문입니다. 예를 들어, 링크하는 동안 나머지 공간을 모두 HEAP에 할당하고 힙의 끝 부분에 초기 스택 포인터를 배치하여 힙으로 커지도록 OS가 힙의 시작 부분부터 시작하여 할당한다는 것을 알고 initial_sp 스택을 포기하기 직전에 OS 스택을 할당합니다. 그런 다음 모든 공간이 작업 스택 및 기타 동적으로 할당 된 메모리를 할당하는 데 사용됩니다.