ProgramingTip

힙 대신 스택을 사용하는 것이 가장 좋은 언제입니까?

bestdevel 2020. 12. 11. 19:13
반응형

힙 대신 스택을 사용하는 것이 가장 좋은 언제입니까?


C ++에서 스택을 사용하는 것이 가장 좋은시기는 언제입니까? 힙을 사용하는 것이 가장 좋은시기는 언제입니까?


현재 함수가 반환되지 않은 후 변수가 사용되지 않을 때 스택을 사용합니다. 현재 함수의 수명을 초과하여 변수의 데이터가 필요할 때 힙을 사용합니다.


일반적으로 스택에 거대한 개체를 생성하지 않습니다.

  • 스택에 객체를 생성하면 객체를 정리 (읽기 삭제)하는 기억하는 부담에서 해냅니다. 그러나 스택에 너무 많은 객체를 생성하면 스택 오버플로가 많은 가능성이 있습니다.
  • OS가 제공 할 수있는 메모리 (스택보다 훨씬 큰)를 사용할 수있는 메모리를 해제해야합니다. 또한 힙에 너무 자주 개체를 생성하면 메모리가 조각화되어 애플리케이션 성능에 영향을 미치게됩니다.

사용중인 메모리가 생성중인 범위로 엄격하게 제한되는 경우 스택을 사용하십시오. 메모리 누수를 방지하는 데 유용합니다. 메모리를 사용하려는 위치를 정확히 알고 더 이상 필요하지 않은시기를 알고 있으므로 메모리가 정리됩니다.

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 )

따라서 위의 예제를 다시 생성 비용 증가 :: 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
}

많은 언급 된 규칙에 대한 예외는 일반적으로 함수 범위 밖에서 필요하지 않습니다.

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


경험상 가능한 한 스택을 사용하십시오. 즉, 해당 범위에서 변수가 필요하지 않을 때.

더 빠르고 단편화가 적으며 malloc 또는 new 호출과 관련된 다른 오버 헤드를 피할 수 있습니다. 스택에서 할당하는 것은 몇 가지 어셈블러 작업, malloc 또는 new는 효율적인 구현에서 수백 줄의 코드입니다.

힙을 사용하는 것이 최선의 방법은 아닙니다. 피할 수 없습니다. :)


이 질문은 (실제로 속이지는 않지만) 며칠 전에 질문했던 스택 및 힙은 무엇이며 어디에 있습니까?와 관련이 있습니다 .


런타임시 개체에 대한 공간 할당에만 힙을 사용합니다. 컴파일 시간에 크기를 알고 있다면 스택을 사용하십시오. 함수에서 힙 할당 객체를 반환하는 대신 쓸 수 있도록 함수에 버퍼를 전달합니다. 이렇게하면 함수가 배열 또는 기타 스택 기반 구조로 호출되는 곳에 버퍼를 할당 할 수 있습니다.

malloc () 문이 적을수록 메모리 누수 가능성이 줄어 듭니다.


질문이 잘못 형성되었습니다.

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

할당은 SP에 대한 "증가"일 뿐이며 모든 "할당"은 현재있는 함수의 호출 시간에 수행되기 때문에 스택이 빠릅니다. 힙 (또는 무료 저장소) 할당 / 할당은 더 많은 시간과 오류가 발생하기 쉽습니다. .

참고 URL : https://stackoverflow.com/questions/102009/when-is-it-best-to-use-the-stack-instead-of-the-heap-and-vice-versa

반응형