2017-03-13 16 views
1

if 조건을 다음 코드에서 실행하여 다음 코드를 작성할 수있는 경우는 어떻게됩니까? 내가 아는 한, if 문을 실행할 어떤 원인도 연관시킬 수 없습니다.호출 된 메모리가 NULL 인 것으로 나타납니다.

#include <stdio.h> 
#include <stdlib.h> 
void main(void){ 
int Nod = 1024 * 8; //Nod contains the number of nodes 
double *MM; //MM is a square matrix it can contain very large number of data 10^10 
MM = calloc(8 * Nod * 8 * Nod, sizeof(double)); 
if (MM == NULL)exit(0); 
//then MM will then be passed to some other functions say 
eigenvalue(MM);} 

매우 큰 프로그램의 중간에이 체크가있는 FEM 코드로 작업하고 있습니다. 흥미로운 사실은 코드를 실행할 때 예외적 인 동작을 나타내는 것입니다. 때로는 프로그램이 여기에서 멈추는 경우가 있습니다. 때로는 그냥 잘 작동합니다. 프로그램이 거친 메쉬로 실행될 때, 즉 Nod이 계산할 노드의 수가 적을 때 프로그램이 제대로 작동한다는 점을 언급해야합니다. 그러나 미세한 메쉬가 사용되면 불행하게도 프로그램이 중단됩니다. 이 프로그램은 128GB RAM이있는 미니 워크 스테이션에서 실행됩니다. 이 프로그램은 1GB (또는 그 이상)의 RAM을 차지합니다.

+2

특정 프로그램은 수행 된 분기에 관계없이 항상 0 상태로 반환됩니다.주 함수 (그리고 주 함수 만)는 실행이 닫는 괄호에 도달 할 때 암시적인'return 0; '을 가지며 리턴합니다. – StoryTeller

+4

'8 * Nod * 8 * Nod'는 2³²이므로 정수가 넘치게됩니다. 'int'보다 큰 타입을 사용하십시오. – mch

+1

는 calloc 및 가능한 반환 값에 대한 맨 페이지를 읽습니다. –

답변

0

:

The malloc() and calloc() functions return a pointer to the allocated memory that 
    is suitably aligned for any kind of variable. On error, these functions return 
    NULL. NULL may also be returned by a successful call to malloc() with a size of 
    zero, or by a successful call to calloc() with nmemb or size equal to zero.e here 

지금 귀하의 경우는 NULL을 반환하는 유일한 다른 이유 때문에 제로 크기의 메모리를 할당에 이슬 아니에요 메모리를 할당 실패입니다. 스 니펫에서 32GB의 RAM 인 4294967296 요소 (1024 * 1024 * 64 * 64)의 크기 (8 바이트)를 할당한다는 것을 보여줍니다. 이제 시스템에 해당 양의 RAM이 있습니다.하지만 주어진 시간에 연속 할당 가능 블록에 모두 들어 있지 않아서 calloc이 실패 할 수 있습니다.

조심하는 또 다른 것은

0으로 설정되어 있지만 아마도 가장 안전한 조합이 2 참조 PROC 남자 페이지 또는 커널 문서 /로 설정 될 기본 overcommit_memory에 의해

/proc/sys/vm/overcommit_memory 
or vis sysctl vm.overcommit_memory 

에 의해 주로 지배 메모리 오버 커밋이다 VM/overcommit-accounting에 대한 자세한 내용은 여기를 참조하십시오.

vm.overcommit_ratio 
vm.overcommit_kbytes 
vm.nr_overcommit_hugepages 

또한 시스템이 메모리 초과 사용을 처리할지 여부를 결정하는 다른 sysctl 설정입니다.

32 비트 Linux 컴퓨터에서 메모리 초과분을 허용하지 않기 위해 최선을 다했지만 여전히 null을 반환하지 않는 거대한 32Gb 호출자를 얻을 수있었습니다 (자신이 이상하다고 생각하는) PAE가 적은 32 비트 컴퓨터는 총 4Gb의 가상 메모리에만 주소를 지정할 수 있으며 PAE가있는 경우에도 한 번에 4Gb를 주소 지정할 수 있습니다.

+0

그냥 언급하자면, 지금 당장 4GB RAM을 가진 내 PC에서 프로그램을 테스트하고 있습니다. 질문을 올렸을 때, 프로그램은 명시된 줄에서 실패하는 것으로 나타났습니다. 그러나 재미있게 프로그램은 지금 달리고있다. ..! 그리고 훨씬 밀도가 높은 메쉬로 ...! 나는 단지이 힌트를 가지고 싶다 ...이 변칙적 인 행동을 일으키는 것은 무엇인가. –

+0

본질적으로 Toby Speight가 만든 두 번째 요점과 같은 제안을 많이했습니다 ... 32GB로가는 방법을 보여주는 단어와 숫자가 몇 가지 더 있습니다. 4Gb 램 머신에서 32Gb 오브젝트를 할당 할 수 있다는 것은 이상합니다. long의 크기가 1 바이트가 되더라도 (물론 그렇지는 않습니다) 여전히 4Gb를 할당 할 것입니다 ... e 라이브 OS가있는 4Gb 머신 4Gb를 할당 할 수 있다고 믿기 어렵습니다. 어쩌면 그것은 비현실적인 기억 일 것입니다 : 4Gb 머신에서 얼마나 많은 교환을 했습니까? – louigi600

+0

@AhmedAfifKhan 그 행동은 결코 "이상한"것은 아닙니다 - 실제로 특정 시간에 사용 가능할 수도 있고 사용되지 않을 수도있는 엄청난 양의 메모리를 할당하려고합니다. 그리고 직접 반환 값을 확인하지 않으므로 * 할당 후에 프로그램이 실패합니다. – tofro

6

두 명백한 문제 :

  1. 계산 8 * Nod * 8 * Nod는 결과를 저장하기 (플랫폼)에 충분히 큰되지 않을 수도 타입 int, 될 것입니다. 대신 size_t Nod이 필요합니다. 값이 일정하지 않은 경우 오버플로 (GCC의 __builtin_mul_overflow()과 같은 플랫폼 별 기능을 사용)를 확인하는 것이 좋습니다.
  2. calloc()의 결과는 NULL이 아닌지 검사하지 않고 사용합니다. 할당 기가 충분히 큰 연속 블록을 찾을 수 없으면 실패하고, 계속하기 전에 테스트해야합니다.

절대은 오류를보고하는 데 사용하는 라이브러리 함수의 반환 값을 무시합니다. 남자 페이지에서

+0

단지 데이터 형식 오버플로이면 매번 실패하지 않습니다. – louigi600

+0

@ louigi600 : 그것은 다릅니다. 서명 된 오버플로는 ** undefined **이므로 아무 것도 의존 할 수 없습니다. "가장 좋은"경우 (최악의 경우)에는 'size_t'로 변환 할 때 데이터에 충분히 큰 값으로 끝납니다. 운이 좋으면 즉각적인 잘못이나 부적절한 가치를 얻고 프로그램을 중단하고 디버깅을 장려하십시오. –

+0

@ 토니 S. 오케이.하지만 그래도 그는 가상 메모리가 부족한 4Gb 시스템에서 거대한 32Gb 블록을 어떻게 할당합니까? 32 비트 머신 (malloc이 실패하면 exit (1)이 있음)을 점검했고, 0으로 종료되었습니다 ... 어떻게 된 일입니까? 나는 당황했다! – louigi600