2009-03-09 5 views

답변

27

정상 선언 스택에 배치됩니다. 함수가 반환 될 때 스택 포인터는 함수가 호출되기 전의 값으로 돌아가므로 메모리가 자동으로 회수됩니다.

Malloc 기반 선언은 '힙'에서 할당되므로 프로그래머가 할당 및 할당 해제를 관리해야합니다.

+0

이것은 전역 적으로 선언 된 변수에도 적용됩니까? – samoz

+0

아니요, AFAICR 전역 적으로 선언 된 변수는 응용 프로그램의 알려진 저장소 요구 사항에 따라 O/S가 별도로 설정하는 별도의 메모리 블록 인 "데이터 세그먼트"에 공백이 있습니다. – Alnitak

+0

전역 변수는 모듈을 포함하는 모듈이 언로드되거나 프로세스가 종료 될 때 "해제"됩니다. – Michael

11

malloc로 선언 된 것만 큼 자유롭게 포인터를 사용할 필요는 없습니다. 또한 자동적으로 그 범위를 벗어나면 폐기 될 스택

int a = 3; 
int* p = &a; 

및 (포인터와 함께)이 메모리의 메모리 위치를 가리키는 포인터를 선언 할 수있다. malloc을 사용하면 힙에 같은 메모리가 할당되므로 수동으로 정리 작업을 처리해야합니다.

+0

명확하게 설명하자면 : 포인터 분실은 스택에 만들어지고 그들은 힙에 할당 된 데이터에 대한 메모리 주소를 보유합니다. 스택은 32 비트 시스템에서 4 바이트를, 64 비트 시스템에서는 스택에서 8 바이트를 차지합니다. –

+0

@ 브라이언 : 설명해 주셔서 고맙습니다. 내 편집으로 내 대답이 기술적으로 정확 해 졌다고 생각합니다. –

8

언어는 스택과 힙 사이를 선택합니다.

당신은 스택과 힙 사이에 선택하는 이유, 이유 : 당신은 당신의 코드 블록의 범위를지나 사용할 수 있도록 의도적으로 자신을 해제하지 않는 힙에

  • 변수 또는 기능.
  • 스택과 함께 작업하는 것이 힙과 비교하면 더 효율적입니다.
  • 런타임시 스택의 객체 또는 배열 크기를 선택할 수 없으므로 여기에서 힙이 사용됩니다.

은 왜 힙이 자동으로 해제 할 수 없습니다 당신이 메모리를 완료하면 알 수있는 방법이 없습니다

때문입니다. 가비지 콜렉션을 에뮬레이트하는 방법이 있지만 스택에 더 이상 변수가없고 힙의 데이터에 대한 포인터를 보유하는 힙이있는 경우에 관련됩니다. 힙 대

스택에 더 :

C 언어의하자 당신이 스택 또는 힙에 변수를 정의 할 것인지 여부를 선택했다.

  • 스택의 변수는 scope에서 벗어날 때 자동으로 해제됩니다.
  • 힙의 변수는 자동으로 해제되지 않습니다.

malloc은 힙에 변수를 만듭니다. int x와 같은 간단한 선언; 스택에 변수를 만듭니다.

See further reading on stack vs heap in my answer here.

포인터 :

그냥 명확히하기 : 포인터 한다거나 할 스택에 생성되고, 그들은 힙에 할당 된 데이터를 메모리 주소를 누르고 있습니다. 스택은 32 비트 시스템에서 4 바이트를, 64 비트 시스템에서는 스택에서 8 바이트를 차지합니다.

+0

내가 본 적이 없기 때문에 관심이 없다. 코드 블록을 입력 할 때마다 컴파일러가 반드시 새 스택 프레임을 만들고 해당 블록의 끝에서 스택 포인터를 되돌릴 수 있습니까? – Alnitak

+0

@Alnitak : 내 생각 엔 최적화 수준에 달려 있다고 생각합니다. 컴파일러는 코드를 인라인하여 함수 호출을 완전히 제거 할 수도 있습니다! – Christoph

+0

필자는 함수 호출이 아닌 함수 내부의 블록을 더 생각하고있었습니다. – Alnitak

-9

많은 사람들이 스택과 힙 할당의 차이점에 대해 대답하는 반면 매우 바람직한 질문인데, 근본적인 대답은 언더 레이 시스템이 여러분에게 뭔가를 노출해서는 안된다는 것입니다.

메모리를 할당 할 때 메모리를 할당 할 때 걱정하지 않아도됩니다. 시스템은 사용자가 더 이상 액세스 (포인트 또는 참조)가 없다는 것을 알기에 충분히 똑똑해야하므로 자동으로 메모리를 다시 사용할 수 있습니다.

Java 및 C#과 같은 최신 언어가이 작업을 수행했습니다.

+0

이것은 논쟁의 여지가 있으며 질문에 대답하지 않는다.또한 언어의 나이와는 아무런 관련이 없습니다 (가비지 수집을 사용하는 오래된 언어의 예로서 Lisp을 참조하십시오). – rmeador

+0

@rmeador - 나는 동의한다 –

+0

나는 "당신이 기억을 할당 할 때, 당신이 그것을 돌려 줄 걱정할 필요가 없다"는 말은 매우 순진하다고 생각한다. 환경에 가비지 수집이 포함되어 있더라도 항상 되돌려 주어야한다고 걱정할 것입니다. –

0

더 이상 만든 점은 this post입니다.

3

알 니 탁이 정확합니다. 나는 "stack"이 실제로 무엇을 의미하는지 지적하고 싶습니다.

프로그램이 함수를 호출 할 때 함수는 일정량의 작업을 수행 한 다음 반환하고 다음 코드 행으로 계속 진행합니다. 이 함수는 함수가 완료 될 때 반환 할 위치를 알 수 없습니다. 따라서이 기계는 함수를 호출하기 전에 프로그램에서 다음 명령문의 주소를 푸시하는 데 사용되는 각 프로그램에 대한 호출 스택을 가지고 있습니다. "return"문은 프로그램 주소를 간단히 표시하고 점프합니다.

스택은 임시 공간의 편리한 스크래치 패드이기도합니다. 스택의 사용하지 않는 영역에 쓸 수 있습니다. C 함수 안에서 지역 변수를 선언하는 것은 정확히 이것을합니다. 함수가 반환 될 때 스택은 정리 ​​공간을 확보하거나 해제하거나 다른 방법으로 처리 할 필요가 없습니다. 어쨌든 임시 공간 이었기 때문에 스택이 범위를 벗어납니다.

반대로 malloc()을 호출하면 프로그램에 대한 메모리를 명시 적으로 설정하고 프로그램이 실행되는 동안 범위에 남아있는 힙에서 메모리를 할당합니다. 따라서 메모리가 free()이 아니면 메모리가 할당 된 상태로 남게됩니다.

2

필요성은 포인터를 선언했는지 여부와 상관없이 malloc() 메모리를 사용했는지 여부에 달려 있습니다. 브라이언 본디처럼

전에 말했듯이, 변수 (" int number", " char string[10]", " float your_boat", 등) 다음 코드는 펑션 블록을 떠날 때와 같은 범위에서 떨어질 때 멀리 이동합니다. 따라서 free()을 호출 할 때 질문의 포인터 (" temp")가 사라지지 않습니다. malloc()을 호출 할 때 할당 된 코드가 사라집니다. 포인터가 그대로 남아 있습니다. 즉, 예제 코드 바로 다음에 " int *temp;"을 말할 필요없이 " temp = &some_other_variable"이라고 말할 수 있습니다.

누군가가 이제까지 그들은 또한, 즉 프로그램, 메모리를 주장 것이며, 그 데이터는, 당신은

을 말할 수있을 것이라고 발표 할 것을 요구하지 않았다 malloc()를 호출 할 일이 있다는 기능을 구현하는 경우

나중에

free(temp); 

말을하지만이 구현되는 방식 malloc() 아니다없이

int * temp = (int*)malloc(sizeof(int)); 

.

5

C는 스택이나 힙에 대한 개념이 없다는 점에 유의해야합니다. 위의 응답은 99 %의 정확하고 정확한 통찰력을 제공합니다.

C 개체 세 저장 기간을 정의 정적, 자동는 할당. (§6.2.4.1)

정적 개체 (예 : 전역 변수)는 전체 프로그램 기간 동안 사용할 수 있습니다.

자동 개체는 해당 변수가 범위 내에있는 한 존재합니다. 그들은 범위를 벗어나 자마자 존재를 멈 춥니 다.

두 가지 극단임을 유의하십시오. C는 사이에 포인트를줍니다 : 할당 된 개체입니다. (은 동적으로 할당 된 메모리입니다.) 은 개체의 시작과 끝을 컴퓨터에 알려줍니다. 그리고 이것은 표준 함수 malloc() (또는 파생 상품) 및 free()을 사용하여 수행됩니다.

엄밀히 말하자면, 이어야합니다. 은 무료입니다 (). 아니면 당신이 할 수 있습니다 (당신은 이것에 대한 정식 표준을 읽어야 할 것입니다)하지만, 프로그램이 종료되기 바로 전에 의 메인() 끝에 그것을 모두 할 수 있습니다. 또는 운영체제에 남겨두면됩니다 (대부분은 아니지만 대부분). 그러나 다시 말하자면 - 으로 전화하면 객체가 생깁니다. malloc(), 프로그램이 종료 될 때 밖으로 나가십시오. 종료됩니다.

여기서 실질적인 영향에 대해 자세히 이야기 할 필요는 없습니다. 메모리는 유한합니다. 메모리가 부족해지기 전에 너무 많은 바이트 만 할당 할 수 있습니다. static 개체를 사용하면 모든 것이 낭비됩니다. 덩어리 또는 하나의 큰 덩어리 인 메모리를 재사용하려고 시도하면 어떤 경우에도 동적 할당 방식과 유사합니다. 을 사용하면 수명이 긴 오브젝트에 대해 스토리지를 사용하면 가능한 한 큰 범위가되도록합니다. 어쨌든 정적 오브젝트에 해당합니다.

- 이제

, 몇 가지 메모 : temp 여기에 자동 객체입니다

{ 
    int *temp = malloc(sizeof(int)); 
    *temp = 5; 
    //free(temp); 
} 

참고.범위로 끝나기 만하면 끝납니다.} 그러나 객체 을 가리키고 있습니다. 그 주소에 free()를 부를 때까지 존재할 것입니다. temp에는 그 주소의 유일한 복사본이 있기 때문에 temp이 범위를 벗어나면 free()를 호출 할 기회가 손실됩니다. 일부 메모리는 영구적으로 할당되지만 아직 사용할 수 없습니다. 이를 메모리 누수이라고합니다.

가비지 수집은 객체 저장을 관리하는 또 다른 방법입니다. } 상기

{ 
    int *temp = gc_malloc(sizeof(int)); 
    *temp = 5; 
} 

경우 컴퓨터가 할당 된 개체에 대한 마지막 참조, temp가 손실 된 것을 결정할 것이며, 그것을 해제하는 것은 좋은 생각이 될 것이라고 : C의 구현처럼 보일 수 있습니다.

무료() 객체 (간단한 예제가 생각할 수있는 작은 사안이 아닌)에 대해 걱정할 필요가없는 트레이드 오프이지만 gc_malloc()은 간단한 malloc()과 temp이 범위를 벗어나는 곳에서 보이지 않는 코드가 실행됩니다. 그리고 컴퓨터가 temp이 마지막 참조 였다고 결정할 수있는 완전히 다른 주제입니다. (실제적인 해결책으로는 "int * temp"주위에 더 많은 코드를 작성해야 할 수도 있습니다.)

관련 문제