문제

저는 임베디드 프로세서(400MHz Intel PXA255 XScale)를 작업 중인데, '새로운' 작업을 만족시키기에 메모리가 충분하지 않은 경우를 본 적이 있다고 생각했습니다.프로그램이 충돌하지 않았기 때문에 다른 스레드가 메모리를 해제했다고 가정했으며 이는 단지 일시적인 일이었습니다.이는 매우 중요한 코드이므로 종료할 수 없으며 일종의 오류가 원격 사용자에게 반환되어야 합니다.

다음과 같은 작은 수정 사항이 문제를 해결하기에 충분합니까, 아니면 더 좋은 방법이 있습니까?모든 '새 항목'을 다음 코드로 바꾸기 전에 물어볼 것이라고 생각했습니다.

char someArr[];
do{ 
    someArr = new char[10]; 
    Sleep(100); // no justification for choosing 100 ms
} while ( someArr == NULL );

수면이 도움이 되나요?최대 재시도 횟수를 설정해야 합니까?어디에서나 정적 초기화를 사용할 수 있습니까?

최종 업데이트: 도움이 되는 답변에 진심으로 감사드립니다. 그런데 메모리 할당 실패 여부를 확인하는 코드에서 오류가 발생한 것으로 확인되었습니다.나는 이러한 모든 대답을 염두에 두고 가능한 한 많은 malloc과 new를 대체할 것입니다(특히 오류 처리 코드에서).

도움이 되었습니까?

해결책

이것을 공격하는 몇 가지 방법이 있습니다.

답변해야 할 몇 가지 질문 :

1. 응용 프로그램이 메모리 누출 되어이 메모리 조건이 낮습니까?

2. 응용 프로그램이 단순히 특정 단계에서 너무 많은 메모리를 사용 하여이 메모리 조건이 낮습니까?

제품에 대한 자세한 메모리 로깅 도구를 제공 할 수있는 Windows CE Appverifier 도구를 사용하여 1과 2를 조사 할 수 있습니다. 다른 힙 랩핑 도구는 제품 설계에 따라 유사한 정보를 제공 할 수 있으며 (고성능이 높을 수 있음).

http://msdn.microsoft.com/en-us/library/aa446904.aspx

3.이 과정에서 메모리를 매우 자주 할당하고 자유롭게 할당하고 있습니까?

Wind 이 경우 물리적 메모리가 충분하지 않더라도 가상 메모리가 부족할 수 있습니다. 맞춤형 블록 할당자를 사용하는 것은 일반적 으로이 문제에 대한 완화입니다.

4. 매우 큰 기억 블록을 할당하고 있습니까? (> 2MB)

3과 관련하여 프로세스 가상 메모리 공간을 소진 할 수 있습니다. OS 버전에 다소 의존하는 트릭이 있으며 공유 VM 공간에서 프로세스 공간 외부에서 메모리를 할당합니다. VM이 부족하지만 물리적 RAM이 부족한 경우 도움이 될 수 있습니다.

5. 많은 DLL을 사용하고 있습니까?

OS 버전에 따라 3과 관련하여 DLL은 사용 가능한 총 VM을 매우 빠르게 줄일 수 있습니다.

추가 점프 포인트 :

CE 메모리 도구의 개요

http://blogs.msdn.com/ce_base/archive/2006/01/11/511883.aspx

대상 제어 창 'mi'도구

http://msdn.microsoft.com/en-us/library/aa450013.aspx

다른 팁

당신은 지역 추론을 통해 글로벌 문제를 해결하려고 노력하고 있습니다. 글로벌 문제는 전체 장치에 운영 체제 및 모든 응용 프로그램에 대해 제한된 양의 RAM (및 백업 스토어)이 있다는 것입니다. 이 양의 RAM이 초과되지 않도록하려면 몇 가지 옵션이 있습니다.

  • 각 프로세스는 시작 시간에 프로세스 당 결정될 고정 된 양의 RAM으로 작동합니다. 프로그래머는 모든 것이 맞는지 확인하기 위해 추론을합니다. 그래서, 예, 모든 것을 정적으로 할당 할 수 있습니다. 그것은 단지 많은 일입니다 시스템 구성을 변경할 때마다 할당을 재고해야합니다..

  • 프로세스는 자신의 메모리 사용 및 요구를 알고 있으며 필요한 메모리에 대해 지속적으로 조언합니다. 그들 그들이 기억이 떨어지지 않도록 협력하십시오. 이는 시스템의 적어도 일부 프로세스가 내부 캐시의 크기를 변경하여 자체 메모리 요구 사항을 조정할 수 있다고 가정합니다. Alonso와 Appel은 a 이 접근법에 대한 논문.

  • 각 프로세스는 메모리가 소진 될 수 있음을 알고 있습니다. 최소 금액의 메모리를 소비하는 상태로 실패. 종종이 전략은 메모리 외 예외를 통해 구현됩니다. 예외는 Main ()에서 또는 근처에서 처리되며 메모리 외 이벤트는 본질적으로 프로그램을 처음부터 다시 시작합니다. 이 장애 조치 모드는 사용자 요청에 응답하여 메모리가 증가하면 작동 할 수 있습니다. 프로그램의 메모리 요구 사항이 사용자가하는 것과 독립적 인 경우 스 래싱으로 이어질 수 있습니다.

위의 제안은 시나리오와 일치하지 않습니다. 대신, 당신은 바라고 있습니다 다른 프로세스는 문제를 해결할 것입니다 그리고 필요한 기억이 결국 나타납니다. 당신은 운이 좋을 것입니다. 당신은 그렇지 않을 수도 있습니다.

시스템이 안정적으로 작동하기를 원한다면 시스템에서 실행되는 모든 프로세스의 설계를 재고 제한된 메모리를 공유 할 필요성에 비추어. 예상보다 더 큰 일일 수도 있지만 문제를 이해하면이 작업을 수행 할 수 있습니다. 행운을 빕니다!

다른 답변에는 좋은 것들이 많이 있지만, 모든 스레드가 비슷한 루프에 들어가면 프로그램이 교착 상태가 될 것이라고 덧붙일 가치가 있다고 생각했습니다.

이 상황에 대한 "올바른"대답은 아마도 프로그램의 다른 부분에 대한 엄격한 한계가있어 메모리를 과도하게 소비하지 않도록하는 것입니다. 아마도 프로그램의 모든 부분에서 주요 섹션을 다시 작성해야 할 것입니다.

다음으로 가장 좋은 솔루션은 할당 실패 시도가 나머지 프로그램에 더 많은 메모리가 필요하다는 것을 알 수있는 콜백을하는 것입니다. 아마도 프로그램의 다른 부분은 평소보다 일부 버퍼를 더 공격적으로 해제하거나 검색 결과를 캐시하는 데 사용되는 메모리를 해제 할 수 있습니다. 프로그램의 다른 부분에 대한 새로운 코드가 필요합니다. 그러나 전체 프로그램에 대한 재 작성을 요구하지 않고 점차적으로 수행 할 수 있습니다.

또 다른 솔루션은 프로그램이 MUTEX로 대규모 (임시) 메모리 요청을 보호하도록하는 것입니다. 나중에 다시 시도 할 수 있다면 메모리가 곧 출시 될 것이라고 확신하는 것 같습니다. 많은 메모리를 소비 할 수있는 작업에 뮤트를 사용하는 것이 좋습니다.이를 통해 다른 스레드가 필요한 메모리를 해제 할 때 즉시 스레드가 깨어날 수 있습니다. 그렇지 않으면 메모리가 즉시 해방 되더라도 실이 10 분의 1 초 동안 잠을 자게됩니다.

또한 수면 (0)을 시도 할 수도 있습니다. 이렇게하면 다른 모든 스레드가 100 밀리 초의 문장을 기다리지 않고 잠을 자면 스레드가 즉시 제어를 회복 할 수 있습니다. 그러나 적어도 하나의 스레드가 여전히 실행되기를 원한다면 제어를 포기할 때까지 기다려야합니다. 이것은 일반적으로 Linux 시스템의 10 밀리 초입니다. 마지막으로 확인했습니다. 나는 다른 플랫폼에 대해 모른다. 자발적으로 잠들었다면 스레드가 스케줄러에서 우선 순위가 낮을 수 있습니다.

귀하의 질문에 따라, 나는 당신의 힙이 여러 스레드간에 공유된다고 가정합니다.

그렇지 않은 경우 위의 코드가 작동하지 않습니다. 루프가 실행되는 동안 아무것도 힙에서 해제되지 않기 때문입니다.

힙이 공유되면 위의 작업이 작동 할 것입니다. 그러나 공유 힙이있는 경우 "새"를 호출하면 스핀 잠금 장치 (있는 것과 유사한 루프이지만 CAS 명령어를 사용)가 발생하거나 일부 커널 리소스를 기반으로 차단됩니다.

두 경우 모두, 당신이 가진 루프는 시스템의 처리량을 줄입니다. 더 많은 컨텍스트 스위치가 발생하기 때문에 "메모리가 이제 사용할 수있는"이벤트에 응답하는 데 시간이 더 걸리기 때문입니다.

"신규"및 "삭제"연산자를 재정의하는 것을 고려할 것입니다. 새 새로운 실패가 없으면 다른 스레드가 자유 메모리를 대기 대기 대기 대기 한 다음 삭제 된 "새"스레드를 신호하거나 CAS를 사용하여 카운터 변수를 증가시킬 수 있습니다.

더 나은 처리량을 제공하고 조금 더 효율적이어야합니다.

몇 가지 요점 :

  • 임베디드 프로그램은 종종 시작시 모든 메모리를 할당하거나 이와 같은 상황을 피하기 위해 정적 메모리 만 사용합니다.
  • 장치에 정기적으로 메모리를 해제하는 다른 것이 없다면 솔루션이 효과적이지 않을 것입니다.
  • 내가 가진 독사는 64MB RAM을 가지고 있습니다. 32MB 미만의 것으로 생각하지 않습니다. 응용 프로그램을 얼마나 많이 사용하고 있습니까?

두 번째로 해야 할 가장 현명한 일은 메모리의 정적 할당을 사용하여 무슨 일이 일어나고 있는지 어느 정도 알 수 있도록 하는 것입니다.동적 메모리 할당은 리소스가 제한된 시스템에 적합하지 않은 데스크톱 프로그래밍의 나쁜 습관입니다(훌륭하게 관리되고 제어되는 메모리 관리 시스템을 만드는 데 상당한 시간과 노력을 들이지 않는 한).

또한 장치의 OS(이와 같은 고급 ARM 장치가 OS를 실행하는 경향이 있다고 가정)가 메모리 처리를 위해 어떤 기능을 가지고 있는지 확인하십시오.

C ++를 사용합니다. 따라서 일부 C ++ 유틸리티를 사용하여 삶을 편하게 만들 수 있습니다. 예를 들어, New_Handler를 사용하지 않는 이유는 무엇입니까?

void my_new_handler() {
    // make room for memory, then return, or throw bad_alloc if
    // nothing can be freed.
}

int main() {
    std::set_new_handler(&my_new_handler);

    // every allocation done will ask my_new_handler if there is
    // no memory for use anymore. This answer tells you what the
    // standard allocator function does: 
    // https://stackoverflow.com/questions/377178
}

New_handler에서는 모든 응용 프로그램에 일부 응용 프로그램에 메모리가 필요하다는 것을 알 수 있도록 모든 응용 프로그램을 신호를 보내고 다른 응용 프로그램에 메모리 요청을 수행 할 시간을 제공하기 위해 약간 기다릴 수 있습니다. 중요하다는 것은 당신입니다 뭔가를하십시오 그리고 아닙니다 조용히 희망 사용 가능한 메모리. 메모리가 충분하지 않은 경우 새 연산자가 핸들러를 다시 호출 할 것이므로 모든 응용 프로그램에 필요한 메모리가 이미 무료인지 여부에 대해 걱정할 필요가 없습니다. 당신은 또한 수 과부하 운영자 새로운 New_handler에 필요한 메모리의 크기를 알아야하는 경우. 내 참조 다른 대답 그렇게하는 방법에. 이런 식으로, 당신은 가지고 있습니다 하나의 중앙 장소 그와 관련된 많은 장소 대신 메모리 문제를 처리합니다.

다른 사람들이 언급했듯이, 이상적으로는, 당신은 선불 디자인과 소프트웨어 아키텍처 로이 문제를 피할 것이지만,이 시점에서 실제로 선택 사항이 아닌 것으로 가정합니다.

다른 게시물에서 언급했듯이, 일부 유틸리티 함수로 논리를 래핑하여 메모리 외 코드를 모든 장소에 쓰지 않도록하는 것이 좋습니다.

실제 문제에 도달하려면 공유 리소스, 메모리를 사용하려고 노력하지만 시스템의 다른 스레드가 공유 리소스를 사용하고 있기 때문에 할 수 없습니다. 이상적으로 원하는 것은 시스템의 다른 스레드 중 하나가 필요한 리소스를 해제 한 다음 해당 리소스를 얻는 것입니다. 모든 할당 및 무료 통화를 가로 채는 방법이 있다면 메모리를 사용할 수있을 때까지 할당 된 스레드가 차단되도록 무언가를 설정할 수 있으며, 메모리가 사용할 수있을 때 할당 스레드가 신호를 보냈습니다. 그러나 나는 그것이 너무 많은 일이라고 생각할 것입니다.

시스템을 완전히 재구성하거나 메모리 할당자를 다시 작성할 수 없다는 제약을 감안할 때, 솔루션은 귀하 (및 팀의 다른 사람들)가 한계를 이해하는 한 가장 실용적이라고 생각합니다. 그리고 그것이 트랙을 일으킬 문제.

이제 특정 접근 방식을 개선하려면 메모리가 얼마나 자주 할당되고 해제되는지 확인하기 위해 워크로드를 측정 할 수 있습니다. 이렇게하면 재 시도 간격이 무엇인지 계산하는 데 더 나은 AY가 제공됩니다.

둘째, 시스템의 해당 스레드의 부하를 줄이기 위해 각 반복마다 타임 아웃을 늘리려 고합니다.

마지막으로, 몇 가지 반복 후 스레드가 진행할 수없는 경우 오류/공황 케이스가 약간 있어야합니다. 이렇게하면 모든 스레드가 시스템의 다른 스레드가 무료 메모리를 기다리고있는 경우 적어도 생중계 케이스를 볼 수 있습니다. 경험적으로 작동하는 것으로 표시된 내용을 기반으로 여러 반복을 선택하거나, 그것에 대해 더 똑똑해지고 메모리를 기다리는 스레드 수를 추적 할 수 있으며, 모든 스레드가 공황 상태 인 경우에는 모든 스레드가 공황 상태입니다.

메모: 이것은 분명히 완벽한 솔루션이 아니며 다른 포스터가 문제를 올바르게 해결하기 위해 전체적으로 응용 프로그램에 대한보다 전 세계적으로 관점을 언급했듯이, 위는 단기적으로 작동 해야하는 실용적인 기술입니다.

분명히 그것은 100 (밀리 초) 수면에서 메모리를 사용할 수있는 합리적인 기대가 있는지 여부에 달려 있습니까? 확실히, 당신은 그것이 시도하는 횟수를 제한해야합니다.

나에게 뭔가 냄새가 나지 않습니다. 흠 ...

임베디드 시스템은 일반적으로 매우 결정적이어야합니다. 아마도 전체 시스템과이를위한 잠재력의 헤드를 검토해야 할 것입니다. 그리고 실제로 실패하면 실제로 실제로 발생합니다.

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