2009-09-21 4 views
5

특정 사용자의 컴퓨터에서 응용 프로그램이 ERROR_NOT_ENOUGH_MEMORY ("이 명령을 처리 할 수있는 저장소가 부족합니다")으로 실패합니다.ERROR_NOT_ENOUGH_MEMORY 문제 해결

우리가 사용하는 Delphi VCL 프레임 워크 내에서 어딘가 깊은 곳으로 오류가 발생하고 있으므로 어떤 Windows API 함수가 책임이 있는지 잘 모르겠습니다.

메모리에 문제가 있습니까?GlobalMemoryStatus를 호출하면 다음과 같은 정보를 제공합니다

  • dwTotalPhys - 1063150000 (~ 1 GB)
  • dwAvailPhys - 26735000 (27 ~ MB)
  • dwAvailPage - 1489000000 (~ 1.4 GB)

페이징 파일에서 너무 많은 공간을 사용할 수있게되면 Windows에서 사용 가능한 실제 메모리가 너무 적게 느껴지지만 실제로 정상인지 아닌지를 알기에는 Windows 가상 메모리 관리에 대해 충분히 알지 못합니다. . 그렇지?

메모리가 아닌 경우 어떤 리소스 제한에 도달 했습니까? 내가 온라인에서 읽은 것, ERROR_NOT_ENOUGH_MEMORY은 응용 프로그램이 여러 한계 (GDI 개체, USER 개체, 핸들 등) 중 하나를 치는 결과 일 수 있으며 메모리가 아닐 수도 있습니다. Windows의 제한 사항에 대한 포괄적 인 목록이 있습니까? 어느 한도에 도달했는지 알아내는 방법이 있습니까? Google을 사용해 보았지만 체계적인 개요를 찾지 못했습니다.

+0

GDI는 첫 번째 호출 포트입니다. 한 사용자의 컴퓨터에서만 발생하는 것은 이상한 일이지만, 그것이 내가 시작할 곳입니다. 그것은 또한 사용중인 핸들 수와 같은 것일 수도 있습니다. 행운을 빌어 요! –

답변

3

이 경우의 범인은 CreateCompatibleBitmap입니다. 분명히 Windows는 장치 의존 비트 맵 (예 : this mailing list discussion 참조)에 사용할 수있는 메모리에 대해 상당히 엄격한 시스템 제한을 적용 할 수 있습니다. 그렇지 않은 경우 시스템에 충분한 메모리와 많은 GDI 리소스가 있더라도 마찬가지입니다. 이러한 시스템 전체 제한은 Windows가 비디오 카드의 메모리에 장치 종속 비트 맵을 할당하기 때문에 명백하게 나타납니다.

이 솔루션은 단순히 장치 독립적 비트 맵 (DIB)을 대신 사용하는 것입니다. 공연). This KB article은 장치에 대해 최적의 DIB 형식을 선택하는 방법을 설명합니다.

(다른 사람들의 답변에서 내 자신의 연구) 자원 한계에 대한 다른 후보 : (이 답변에서)

  • GDI 리소스 - 쉽게 (이 답변에서) GDIView
  • 가상 메모리 조각화 확인
  • 데스크톱 힙 - 내 말 전자에서, here 또는 here
3

이 오류는 나열된 것보다 일반적으로 가상 메모리 공간의 조각화입니다. 총 여유 메모리가 상당히 합리적 인 상황에서 여유 공간은 현재 할당 된 가상 메모리 공간의 다양한 비트로 조각화됩니다. 따라서 총 메모리가 충분하지 않아도 단일 연속 블록으로 메모리 요청을 충족시킬 수 없으면 메모리 부족 오류가 발생할 수 있습니다.

+0

새로운 재부팅에서 똑같은 것을 시도하면 쉽게 확인할 수 있습니다. 사람은 그것을 SO에 대한 질문으로 게시하기 전에 시도했을 것이라고 생각할 것입니다. (그러나 우연한 일은 일어났습니다 ...) –

+0

@ T.E.D. : 재부팅은 단순히 오류 프로세스를 종료하고 다시 시도하는 것보다 효과적이지 않습니다. 각 프로세스는 처음 생성 될 때 자체의 새로운 가상 메모리 공간을 갖습니다. 문제는 대개 장기간 실행되는 응용 프로그램에서 자연스럽게 발생합니다. 또는 크고 작은 메모리 덩어리가 다른 수명 동안 할당되고 할당 취소되는 경우 빠르게 발생합니다. 일반적으로 코드의 일부 청크는 지속적으로 메모리를 할당하고 해제하는 대신 재사용 할 버퍼 목록을 유지해야한다는 지표입니다. – AnthonyWJones

+0

Delphi에서 FastMM을 사용하면 가상 메모리 조각화를 방지하는 데 더 효과적입니다. –

4

모든 가능성을 확인하십시오.

무료 GDIView 유틸리티를 사용하여 GDI 문제를 모니터링 할 수 있습니다. 사용자가 설치 프로그램없이 시작할 수있는 단일 파일입니다.

또한 해당 기계에 ProcessExplorer을 설치하십시오.

기기에 대한 액세스 권한이없는 경우 사용자에게 애플리케이션이 모니터링하는 상태의 스크린 샷을 작성하도록 요청합니다. 아주 좋아, 이것은 당신에게 약간의 힌트를 줄 것이다.

+0

GDIView는 흥미 롭습니다 "the GDI objects"에 대한 자세한 내용은입니다. – Wolf

0

내 대답은 조금 늦을 수 있습니다 볼 수 있지만 모든 문제를 해결하고, 단계별로 진행하고, DC를 생성하고, 해제하고, CompatibleBitmap 대신 DIBSection을 사용하고, 누수 GDI/메모리 도구 등을 사용하여 모든 테스트를 수행합니다.

끝으로 (LOL) :

나는이 두 가지 호출의 우선 순위를 바꿨다. 그런 다음 모든 문제가 수정되었다.

DeleteDC(hdc);  //do it first (always before deleting objects) 
DeleteObject(obj);