문제

나는 문제가 발생하는 C 프로그램 실행 중에서 AVR 마이크로 컨트롤러(ATMega328P).나는 그것을 믿는 것 때문에 스택/힙 충돌을 방지할 수 있을 확인합니다.

는 방법이 있는 시각화 할 수 있습 SRAM 사용하여 스택과 힙?

참고: 프로그램 컴파일 avr-gcc 사용 avr-libc.

업데이트: 실제 문제를 내는 데는 malloc 구현은 실패(로 돌아 NULL).모든 mallocing 일에 시작하고 모든 freeing 의 끝에서 발생하는 응용 프로그램(는 실제로는 결코 이후 주요 응용 프로그램의 일부입니다 무한 루프에서).그래서 나는 확실히 조각이 문제가 되지 않습니다.

도움이 되었습니까?

해결책

당신이 말하는 malloc 이 실패 반환 NULL:

명백한 원인을 찾아야 하는 처음에는 귀하의 힙입니다"전체"수 있습니다.e 이 메모리는 당신이 요청하는 malloc 할당할 수 없기 때문에,그것은 사용할 수 없습니다.

다음과 같은 두 가지 시나리오를 명심:

a:당신이 16 일 K 힙,당신은 이미 malloced10K 와 당신이 시도하고 malloc 더 10K.귀하의 힙은 단순히 너무 작습니다.

b:더 일반적으로,당신은 16k 힙,당신의 무리 malloc//realloc 통화하고 귀하의 힙입니다 50%이하'전':You call malloc 에 대한 1K 고 실패할-무슨 일이야?답-힙 공간이난-이 없 contigous1K 의 메모리는 반환될 수 있습니다.C 힙 관리할 수 있지 않은 컴팩트한 힙 이런 경우,그래서 당신은 일반적으로습니다.있는 기법을 피하기 위해 조각,그러나 그는지 여부를 알기 어려운 경우 이 문제입니다.당신은 로깅을 추가 심해 malloc 및 free 그래서 아이디어를 얻을 수 있습니다 무엇의 동적 메모리는 작업이 수행됩니다.

편집:

당신이 말한 모든 mallocs 발생 시작에서,그래서 분열되지 않습니다.

어떤 경우에,그것은 쉬운 대체하는 동적 할당을 가진 고정되어 있습니다.

오래된 코드 예제:

char *buffer;

void init()
{
  buffer = malloc(BUFFSIZE);
}

새 코드:

char buffer[BUFFSIZE];

일단 당신이 어디든,당신의 링커까지 다양한 종류의 상세한 모든 것이 맞지 않을 수으로 메모리를 사용할 수 있습니다.하는 것을 잊지 마을 줄일 힙 크기는 하지만 조심 중 일부는 런타임 io 시스템 기능 여전히 사용할 수 있습 힙,그래서 당신이 할 수 없을 완전히 제거.

다른 팁

RAM 정적 사용을 사용하여 확인할 수 있습니다 avr-size 유틸리티는 생성 된대로
http://www.avrfreaks.net/index.php?name=pnphpbb2&file=viewtopic&t=62968,
http://www.avrfreaks.net/index.php?name=pnphpbb2&file=viewtopic&t=82536,
http://www.avrfreaks.net/index.php?name=pnphpbb2&file=viewtopic&t=95638,
그리고 http://letsmakerobots.com/node/27115

avr-size -C -x Filename.elf

(AVR 크기 문서 : http://ccrma.stanford.edu/planetccrma/man/man1/avr-size.1.html )

IDE에서이를 설정하는 방법에 대한 예를 따릅니다. Code :: Blocks, Project-> 빌드 옵션 -> 사전/게시물 빌드 단계 -> 구축 후 단계는 다음과 같습니다.

avr-size -C $(TARGET_OUTPUT_FILE)또는
avr-size -C --mcu=atmega328p $(TARGET_OUTPUT_FILE)

예제 빌드 끝의 출력 :

AVR Memory Usage
----------------
Device: atmega16

Program:    7376 bytes (45.0% Full)
(.text + .data + .bootloader)

Data:         81 bytes (7.9% Full)
(.data + .bss + .noinit)

EEPROM:       63 bytes (12.3% Full)
(.eeprom) 

데이터는 SRAM 사용량이며 컴파일 타임에 컴파일러가 알고있는 금액 만 있습니다. 런타임 (특히 스택 사용)에서 생성 된 물건을위한 공간이 필요합니다.

스택 사용 (동적 RAM)을 확인하려면 http://jeelabs.org/2011/05/22/atmega-memory-use/

다음은 현재 사용되지 않은 RAM의 양을 결정하는 작은 유틸리티 기능입니다.

int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

그리고 다음은 해당 코드를 사용하는 스케치입니다.

void setup () {
    Serial.begin(57600);
    Serial.println("\n[memCheck]");
    Serial.println(freeRam());
}

FreeRam () 함수는 힙 끝과 스택에 마지막으로 할당 된 메모리 사이에 몇 바이트가 존재하는 수를 반환하므로 충돌하기 전에 스택/힙이 얼마나 많이 자랄 수 있는지 효과적으로 발생합니다.

스택/힙 충돌을 일으킬 수 있다고 생각되는 코드 주변 의이 함수의 반환을 확인할 수 있습니다.

일반적인 접근법은 알려진 패턴으로 메모리를 채우고 어떤 영역을 덮어 쓰는지 확인하는 것입니다.

스택과 힙을 모두 사용하고 있다면 조금 더 까다로울 수 있습니다. 힙을 사용하지 않을 때 내가 한 일을 설명하겠습니다. 일반적으로, 내가 근무한 모든 회사 (임베디드 C 소프트웨어 영역)는 힙 메모리 가용성의 불확실성을 피하기 위해 소규모 임베디드 프로젝트에 힙을 사용하지 않았습니다. 대신 정적으로 선언 된 변수를 사용합니다.

한 가지 방법은 대부분의 스택 영역을 시작시 알려진 패턴 (예 : 0x55)으로 채우는 것입니다. 이것은 일반적으로 소프트웨어 실행 초기에 작은 코드로, Main ()의 시작시 또는 아마도 Main ()가 시작하기 전에 시작 코드에서 수행됩니다. 물론 그 시점에서 사용중인 소량의 스택을 덮어 쓰지 않도록주의하십시오. 그런 다음 소프트웨어를 잠시 실행 한 후 스택 공간의 내용을 검사하고 0x55가 여전히 손상되지 않은 위치를 확인하십시오. "검사"방법은 대상 하드웨어에 따라 다릅니다. 디버거가 연결되어 있다고 가정하면 마이크로 실행을 중지하고 메모리를 읽을 수 있습니다.

메모리 액세스 브레이크 포인트 (일반적인 실행 중단 점보다 조금 더 멋진)를 수행 할 수있는 디버거가있는 경우 스택 공간의 가장 먼 한계와 같은 특정 스택 위치에서 중단 점을 설정할 수 있습니다. 스택 사용 범위에 도달 할 때 정확히 실행중인 코드가 정확히 표시되기 때문에 매우 유용 할 수 있습니다. 그러나 디버거는 메모리 액세스 브레이크 포인트 기능을 지원해야하며 종종 "저급"디버거에서는 찾을 수 없습니다.

힙을 사용하는 경우 스택과 힙이 충돌 할 위치를 예측할 수 없기 때문에 조금 더 복잡 할 수 있습니다.

임베디드 대상에 힙 / 동적 할당을 사용하지 마십시오. 특히 자원이 제한된 프로세서를 사용합니다. 프로그램이 커짐에 따라 문제가 다시 발생하기 때문에 응용 프로그램을 재 설계하십시오.

하나의 스택 만 사용하고 있다고 가정하고 (RTO 나 다른 것도 아님) 스택이 메모리의 끝에 있다고 가정하면, 힙은 BSS/데이터 영역 이후에 시작되는 동안 자라면서 자라며 자랍니다. 실제로 StackPointer를 확인하고 충돌에 실패하는 Malloc의 구현을 보았습니다. 당신은 그렇게하려고 노력할 수 있습니다.

malloc 코드를 조정할 수 없으면 메모리 시작시 (링커 파일 사용) 스택을 넣을 수 있습니다. 일반적으로 스택의 최대 크기를 알고/정의하는 것이 항상 좋은 생각입니다. 처음에 그것을 넣으면 RAM의 시작을 넘어서 읽는 데 오류가 발생합니다. 힙은 끝에있을 것이며 괜찮은 중행이라면 끝까지 자라지 않을 수 있습니다 (대신 Null을 반환 할 것입니다). 좋은 점은 2 개의 별도 문제에 대해 2 개의 별도 오류 사례가 있다는 것을 알고 있습니다.

최대 스택 크기를 찾으려면 메모리를 패턴으로 채우고 응용 프로그램을 실행하고 얼마나 멀리 떨어져 있는지 확인할 수 있습니다. Craig의 답변도 참조하십시오.

힙에 대한 코드를 편집 할 수 있다면 각 메모리 블록에 몇 개의 추가 바이트 (이러한 낮은 리소스에서 까다로운)로 패드 할 수 있습니다. 이 바이트는 스택과 다른 알려진 패턴을 포함 할 수 있습니다. 스택이 스택 내부에 나타나거나 그 반대를 볼 때 스택과 충돌하는 경우 단서가 될 수 있습니다.

UNIX와 같은 운영 체제에서 매개 변수가 0 인 SBRK ()라는 라이브러리 기능을 사용하면 동적으로 할당 된 힙 메모리의 최상위 주소에 액세스 할 수 있습니다. 리턴 값은 무효 * 포인터이며 임의의 스택 할당 변수의 주소와 비교할 수 있습니다.

이 비교 결과를 사용하여주의해서 사용해야합니다. CPU 및 시스템 아키텍처에 따라 스택은 임의의 높은 주소에서 자라날 수 있으며 할당 된 힙은 낮은 메모리에서 올라갑니다.

때때로 운영 체제에는 메모리 관리에 대한 다른 개념 (예 : OS/9)이있어 힙과 스택을 자유 메모리에 다른 메모리 세그먼트에 배치합니다. 이러한 운영 체제 (특히 임베디드 시스템의 경우)에서 시스템이 일치하는 크기의 메모리 세그먼트를 할당 할 수 있도록 애플리케이션의 최대 메모리 요구 사항을 미리 정의해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top