2008-09-19 2 views

답변

53

현재 함수가 반환 된 후에 변수를 사용하지 않을 때 스택을 사용하십시오. 변수의 데이터가 현재 함수의 수명 이상으로 필요할 때 힙을 사용하십시오.

+3

그걸 해결할 방법이 있습니다. 버퍼에 데이터를 쓰는 함수에 버퍼를 전달하는 것은 하위 스택 프레임에있는 동적 데이터를 "반환"하는 함수를 만드는 좋은 방법입니다. OO와 비슷하지만 훨씬 효율적입니다. –

+6

크기 또한 고려 사항입니다. 스택의 1K가 넘는 항목은 신중하게 고려해야합니다. 때로는 힙 메모리에 스택 포인터를 두는 것이 더 좋습니다 ('Resource Acquisition is Initialization'관용구와 함께) – Arkadiy

+1

하지만 메모리가 클래스의 속성 인 경우 클래스 속성이 포인터가 될지 또는 그렇지 않으면 언제 결정해야합니까? 또한 언제 스마트 포인터를 사용할 수 있습니까? – JagWire

3

런타임시 오브젝트에 대한 공간 만 할당하기 위해 힙을 사용하십시오. 컴파일 할 때 크기를 알고 있으면 스택을 사용하십시오. 함수에서 힙 할당 객체를 반환하는 대신 함수에 버퍼를 전달하여 쓰기 권한을 부여합니다. 그런 식으로 함수가 배열이나 다른 스택 기반 구조로 호출되는 곳에 버퍼를 할당 할 수 있습니다.

더 적은 malloc() 문을 사용하면 메모리 누수 가능성이 줄어 듭니다.

0

질문이 잘못되었습니다.

스택이 필요한 상황, 힙이 필요한 곳, 정적 저장소가 필요한 곳, const 메모리 데이터가 필요한 곳, 무료 저장소가 필요한 곳 ​​등이 있습니다.

할당은 SP를 통한 "증가"이므로 모든 "할당"은 현재 함수의 호출 시간에 수행되기 때문에 스택이 빠릅니다. 힙 (또는 무료 저장) 할당/할당 해제는 더 많은 시간입니다 비싸고 오류가 발생하기 쉽다.

28

엄지 손가락으로 말하면, 스택에 거대한 물건을 만들지 마십시오.

  • 스택에 개체를 만들면 개체를 정리 (읽기 삭제)해야한다는 부담을 덜어줍니다. 그러나 스택에 너무 많은 객체를 만들면 스택 오버플로 가능성이 높아집니다.
  • 개체에 힙을 사용하면 OS가 제공 할 수있는만큼의 메모리를 얻을 수 있습니다. 스택보다 훨씬 넉넉하지만, 완료되면 다시 메모리를 확보해야합니다. 또한 힙에 너무 많은 객체를 너무 자주 만들면 메모리가 조각 나게되어 응용 프로그램의 성능에 영향을 미칩니다.
12

사용중인 메모리가 작성중인 범위에 엄격히 제한되어있을 때 스택을 사용하십시오. 이는 메모리 누수를 피하기 위해 유용합니다. 왜냐하면 메모리를 어디서 사용하고 싶은지 정확히 알기 때문에 더 이상 필요없는 시점을 알기 때문에 메모리가 정리됩니다.

int main() 
{ 
    if (...) 
    { 
     int i = 0; 
    } 
    // I know that i is no longer needed here, so declaring i in the above block 
    // limits the scope appropriately 
} 

그러나 힙은 메모리가 작성 범위를 벗어나 액세스 될 수 있고 스택 변수를 복사하지 않으려는 경우에 유용합니다. 이렇게하면 메모리 할당 및 할당 해제 방법을 명시 적으로 제어 할 수 있습니다.

Object* CreateObject(); 

int main() 
{ 
    Object* obj = CreateObject(); 
    // I can continue to manipulate object and I decide when I'm done with it 

    // .. 
    // I'm done 
    delete obj; 
    // .. keep going if you wish 
    return 0; 
} 

Object* CreateObject() 
{ 
    Object* returnValue = new Object(); 
    // ... do a bunch of stuff to returnValue 
    return returnValue; 
    // Note the object created via new here doesn't go away, its passed back using 
    // a pointer 
} 

명백히 일반적인 문제는 개체를 삭제하는 것을 잊어 버릴 수 있다는 것입니다. 이를 메모리 누수라고합니다. 이러한 문제는 "소유권"(또는 사물을 삭제할 책임이있는 사람)이 정의하기가 더 어려워지는 프로그램이 점점 줄어들면서 점점 더 널리 퍼지고 있습니다.

더 많은 관리 언어 (C#, Java)의 일반적인 솔루션은 가비지 수집을 구현하므로 삭제할 필요가 없습니다.그러나 이것은 배경에 힙 데이터를 검사하기 위해 비 주기적으로 실행되는 무언가가 있음을 의미합니다. 평범하지 않은 프로그램에서는 "가비지 콜렉션"스레드가 튀어 나오고 떼어 내고 삭제해야하는 데이터를 찾고 나머지 프로그램은 실행이 차단되어 다소 비효율적이 될 수 있습니다.

C++에서 메모리 누출 문제를 해결하는 가장 일반적인 방법은 스마트 포인터를 사용하는 것입니다. 이 중 가장 일반적인 것은 boost::shared_ptr이고 (reference counted)

위 예제를 다시 작성하려면 boost :: shared_ptr CreateObject();

int main() 
{ 
    boost::shared_ptr<Object> obj = CreateObject(); 
    // I can continue to manipulate object and I decide when I'm done with it 

    // .. 
    // I'm done, manually delete 
    obj.reset(NULL); 
    // .. keep going if you wish 
    // here, if you forget to delete obj, the shared_ptr's destructor will note 
    // that if no other shared_ptr's point to this memory 
    // it will automatically get deleted. 
    return 0; 
} 

boost::shared_ptr<Object> CreateObject() 
{ 
    boost::shared_ptr<Object> returnValue(new Object()); 
    // ... do a bunch of stuff to returnValue 
    return returnValue; 
    // Note the object created via new here doesn't go away, its passed back to 
    // the receiving shared_ptr, shared_ptr knows that another reference exists 
    // to this memory, so it shouldn't delete the memory 
} 
+0

그리고 나서 move-semantics가있었습니다. –

4

가능한 한 언제든지 스택을 사용하십시오. 변수가 그 범위 밖에서 절대로 필요하지 않을 때.

더 빠르면 조각화가 덜 일어나고 malloc 또는 new를 호출하는 것과 관련된 다른 오버 헤드가 발생하지 않게됩니다. 스택을 할당하는 것은 몇 가지 어셈블러 연산입니다. malloc 또는 new는 효율적인 구현에서 수백 줄의 코드입니다.

힙을 사용하는 것이 절대로 좋지 않습니다 ... 단지 피할 수없는 것입니다. :)

+0

두 개 이상의 어셈블러 연산보다 낫습니다 - 스택이 어느 방향으로 커지는 지에 따라 하나의 더하기 또는 빼기 일뿐입니다. – Eclipse

+0

덧셈과 뺄셈은 항상 단일 연산이 아니라 ... 다른 끝에서 정리를 고려하십시오. 호출 규칙에 따라 add/sub와 일치하는 하위/추가가 있습니다. 스택을 정확히 사용하는 방법과 컴파일러에서 최적화하는 방법에 따라 모두 병합 될 수 있지만 (실제로는 0 인스트럭션으로 종결 될 수 있습니다. .. 또는 매우 특별한 경우, 지침을 뺀 것) – jheriko

8

당신은 함수의 범위를 벗어난 필요하지 않은 지역 변수에 대한 스택을 사용하여 일반적으로해야 그 위에서 언급 한 규칙의 예외 : 그들은 지역의 대형 할당 할 경우

재귀 함수는 스택 공간을 소모 할 수 있습니다 변수 또는 재귀 적으로 여러 번 호출되는 경우. 메모리를 사용하는 재귀 함수가있는 경우 스택 기반 메모리 대신 힙 기반 메모리를 사용하는 것이 좋습니다.

관련 문제