마이크로 컨트롤러에 RAM이 부족하면 어떻게됩니까?


12

우연의 일치 일 수도 있지만 RAM이 부족할 때 재부팅 한 마이크로 컨트롤러 (하드웨어 별 경우 Atmega 328)를 보았습니다. 메모리가 부족할 때 마이크로 컨트롤러가하는 일입니까? 그렇지 않다면 어떻게됩니까?

왜 어떻게? 스택 포인터는 확실히 할당되지 않은 메모리 범위 (또는 롤오버)로 맹목적으로 증가하지만 다음과 같은 상황이 발생합니다. 데이터 (플래시에서 직접 실행되는 코드와 다른 것으로 가정)?

이것이 여기에 있는지 또는 스택 오버플로에 있는지 확실하지 않습니다. 하드웨어가 그 역할을 담당하고 있다고 확신하지만 이것이 옮겨 져야하는지 알려주십시오.

최신 정보

메모리 손상의 실제 메커니즘에 특히 관심이 있음을 지적해야합니다 (SP 롤오버의 결과-> uC의 메모리 매핑 등에 의존합니까?).


8
유효하지 않은 주소에 액세스하려고하면 일부 마이크로가 재설정됩니다. 하드웨어에 구현 된 유용한 기능입니다. 다른 경우에는 아키텍처가 허용하는 경우 코드가 아닌 데이터를 실행하고 워치 독이 가져 오는 루프에 걸릴 수 있습니다. 의.
Spehro Pefhany

2
프로세서에 RAM이 부족한 경우 RAM이 부족해질 수있는 명령이 없습니다. RAM 부족은 전적으로 소프트웨어 개념입니다.
user253751

답변:


14

일반적으로 스택과 힙이 서로 충돌합니다. 그 시점에서 모든 것이 지저분 해집니다.

MCU에 따라 여러 가지 중 하나가 발생할 수 있습니다.

  1. 변수가 손상됩니다
  2. 스택이 손상됩니다
  3. 프로그램이 손상됩니다

1이 발생하면 이상한 행동을 시작합니다. 2가 발생하면 모든 형태의 지옥이 풀립니다. 스택의 반송 주소 (있는 경우)가 손상된 경우 현재 전화가 돌아 오는 위치는 누구의 추측입니다. 당시 기본적으로 MCU는 임의의 작업을 시작합니다. 3이 다시 발생하면 누가 무슨 일이 일어날 지 잘 알고 있습니다. RAM에서 코드를 실행하는 경우에만 발생합니다.

일반적으로 스택이 손상되면 끝났습니다. 바로 MCU에서 발생합니다.

처음에 메모리를 할당하려는 시도가 실패하여 손상이 발생하지 않았을 수 있습니다. 이 경우 MCU에서 예외가 발생할 수 있습니다. 예외 처리기가 설치되어 있지 않으면 대부분 MCU가 중지됩니다 (에 해당 while (1);하는 처리기가 설치되어 있으면 깨끗하게 재부팅 될 수 있습니다.

메모리 할당이 계속 진행되거나 시도가 실패하고 메모리 할당이없는 상태로 계속되면 "누가 아는가?"라는 영역에있게됩니다. MCU는 이벤트의 올바른 조합 (인터럽트로 인해 칩이 재설정되는 등)을 통해 자체적으로 재부팅 될 수 있지만 이러한 일이 발생한다는 보장은 없습니다.

활성화 될 경우 일반적으로 발생할 가능성이 높은 것은 내부 워치 독 타이머 (있는 경우)가 시간 초과되어 칩을 재부팅하는 것입니다. 프로그램이 이러한 종류의 충돌을 통해 완전히 AWOL되면 타이머를 재설정하는 명령이 일반적으로 실행되지 않으므로 시간 초과 및 재설정됩니다.


답변 주셔서 감사합니다. 효과에 대한 훌륭한 요약입니다. 아마도 이러한 손상의 실제 메커니즘에 대한 자세한 내용을 원한다고 지정했을 것입니다. 스택 및 힙에 전체 RAM이 할당되어 스택 포인터가 롤오버되어 이전 변수 / 주소를 덮어 씁니까? 아니면 각 마이크로 메모리 매핑에 덜 의존적입니까? 선택적으로 (아마도 그 자체의 주제 일 것입니다), 나는 그 하드웨어 핸들러가 어떻게 구현되는지 배우고 싶습니다.
Mister Mystère

1
주로 사용중인 컴파일러와 표준 C 라이브러리에 따라 다릅니다. 또한 때로는 컴파일러 구성 방법 (링커 스크립트 등)에 따라 다릅니다.
Majenko

아마도 몇 가지 예를 통해 그것을 확장 할 수 있습니까?
Mister Mystère

아니, 아니 일부 시스템은 다른 세그먼트에 대해 유한 공간을 할당하지만 일부는 그렇지 않습니다. 일부는 링커 스크립트를 사용하여 세그먼트를 정의하지만 일부는 그렇지 않습니다. 관심있는 마이크로 컨트롤러를 선택하고 메모리 할당이 어떻게 작동하는지 연구하십시오.
Majenko

12

다른 견해 : 마이크로 컨트롤러의 메모리가 부족하지 않습니다.

적어도 제대로 프로그래밍되지 않았을 때. 마이크로 컨트롤러를 프로그래밍하는 것은 범용 프로그래밍과 정확히 같지 않으므로 올바르게 수행하려면 제한 조건과 프로그램을 알고 있어야합니다. 이를 보장하는 데 도움이되는 도구가 있습니다. 적어도 링커 스크립트와 경고를 읽는 방법을 찾아서 배우십시오.

그러나 Majenko와 다른 사람들이 말했듯이 잘못 프로그래밍 된 마이크로 컨트롤러에는 메모리가 부족한 다음 무한 루프 (적어도 워치 독 타이머가 재설정 할 수있는 기회를 제공합니다. 워치 독 타이머를 활성화 했습니까?)를 포함하여 무엇이든 할 수 있습니까? )

마이크로 컨트롤러에 대한 일반적인 프로그래밍 규칙은이를 피합니다. 예를 들어, 모든 메모리는 스택에 할당되거나 정적으로 (전역 적으로) 할당됩니다. "new"또는 "malloc"은 금지되어 있습니다. 서브 루틴 중첩의 최대 깊이를 분석하고 사용 가능한 스택에 맞게 표시 할 수 있도록 재귀도 마찬가지입니다.

따라서 필요한 최대 스토리지는 프로그램이 컴파일되거나 링크 될 때 계산 될 수 있으며 대상 프로세서의 특정 프로세서에 대한 메모리 크기 (종종 링커 스크립트로 인코딩 됨)와 비교 될 수 있습니다.

그런 다음 마이크로 컨트롤러에 메모리가 부족하지는 않지만 프로그램이 손상 될 수 있습니다. 이 경우에는

  • 다시 쓰거나 작게 또는
  • 더 큰 프로세서를 선택하십시오 (메모리 크기가 다른 경우가 많습니다).

마이크로 컨트롤러 프로그래밍에 대한 일반적인 규칙 세트 는 모터 산업에서 채택한 MISRA-C 입니다.

필자의 관점에서 SPARK-2014 Ada 하위 집합 을 사용하는 것이 가장 좋습니다. Ada는 실제로 AVR, MSP430 및 ARM Cortex와 같은 소형 컨트롤러를 합리적으로 잘 대상으로하며 본질적으로 C보다 마이크로 컨트롤러 프로그래밍을위한 더 나은 모델을 제공합니다. 그러나 SPARK는 주석을 프로그램 형태로 설명에 추가합니다.

이제 SPARK 도구는 해당 주석을 포함하여 프로그램을 분석하고 해당 속성을 증명하거나 잠재적 오류를보고합니다. 잘못된 메모리 액세스 또는 정수 오버플로를 처리하는 데 시간이나 코드 공간을 낭비하지 않아도 결코 발생하지 않는 것으로 입증되었습니다.

SPARK와 관련된 선행 작업이 더 많지만 신비한 재부팅 및 기타 이상한 동작을 쫓는 데 시간을 소비하지 않기 때문에 더 빠르고 저렴하게 제품을 얻을 수 있다는 경험이 있습니다.

MISRA-C와 SPARK의 비교


3
이것을 +1하십시오. AVR로 포팅 malloc()(및 C ++ 동반자 new)은 아두 이노 사람들이 할 수있는 최악의 일 중 하나이며 포럼에서 많은 코드가 깨진 많은 혼란스런 프로그래머와 아두 이노 스택 교환으로 이어졌습니다. mallocATmega를 사용하는 것이 유익한 상황은 매우 적습니다 .
코너 울프

3
철학 +1, 현실주의 -1 물건이 올바르게 프로그래밍되면이 질문이 필요하지 않습니다. 문제는 마이크로 컨트롤러에 메모리 가 부족할 때 발생하는 문제였습니다 . 메모리 부족을 방지하는 방법은 또 다른 질문입니다. 다시 말하면 재귀는 문제를 해결 하고 스택을 모두 사용할 수있는 강력한 도구 입니다.
PkP

2
@Brian, 나는 바보가 아니기 때문에 분명히 당신에게 동의합니다. 나는 단지 반대로 관점에서 생각하고 싶습니다. 메모리 부족 (스택)이 끔찍한 결과를 깨달았을 때 메모리가 발생하지 않도록하는 방법을 찾고 싶습니다. 그렇게하면 좋은 프로그래밍 조언을 따르는 대신 좋은 프로그래밍 실습을 찾는 데 실질적인 원동력이됩니다 ... 메모리 장벽에 부딪 칠 때 편의를 희생하면서도 좋은 프랙티스를 시행 할 가능성이 높습니다. 그것은 단지 관점
일뿐입니다

2
@PkP : 소리가 크고 선명하게 들립니다. 나는 이것이 실제로 다른 질문에 답하지 않기 때문에 이것을 다른 견해로 분류했다!
Brian Drummond

2
@ MisterMystère : 마이크로 컨트롤러는 일반적으로 메모리가 부족하지 않습니다. 처음 전원을 켰을 때 4096 바이트의 RAM을 가진 마이크로 컨트롤러는 영원히 4096 바이트를 갖습니다. 코드가 존재하지 않는 주소에 잘못 액세스하려고 시도하거나 주소를 계산하는 두 가지 방법이 다른 메모리에 액세스하지 않을 것으로 예상 할 수 있지만 컨트롤러 자체는 주어진 명령을 단순히 실행합니다.
supercat

6

나는 Majenko의 답변을 정말로 좋아하고 직접 +1했습니다. 그러나 나는 이것을 날카로운 점으로 분명히하고 싶다.

아무거나는 마이크로 컨트롤러 메모리가 부족할 때 발생할 수 있습니다.

당신은 정말 일어날 때 아무것도 의존 할 수 없습니다. 머신에 스택 메모리가 부족하면 스택이 손상되었을 가능성이 큽니다. 그리고 그렇게되면 어떤 일이든 일어날 수 있습니다. 변수 값, 스필, 임시 레지스터는 모두 손상되어 프로그램 흐름을 방해합니다. If / then / eles가 잘못 평가 될 수 있습니다. 리턴 주소가 깨져서 프로그램이 임의의 주소로 이동합니다. 프로그램에서 작성한 모든 코드가 실행될 수 있습니다. ( "if [condition] then {fire_all_missiles ();}")와 같은 코드를 고려하십시오. 또한 코어가 연결되지 않은 메모리 위치로 이동할 때 작성 하지 않은 전체 명령을 실행할 수 있습니다. 모든 베팅이 종료되었습니다.


2
부록에 감사드립니다. 특히 fire_all_missiles () 라인이 마음에 들었습니다.
Mister Mystère

1

AVR이 주소 0에서 벡터를 재설정했습니다. 임의의 가비지로 스택을 덮어 쓰면 결국에는 리턴 주소를 덮어 쓰고 "nowhere"를 가리 킵니다. 그런 다음 서브 루틴에서 아무 곳으로도 돌아 오지 않으면 실행은 리셋 핸들러로 점프하는 곳의 주소 0으로 돌아갑니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.