Programing

C ++에서 적절한 스택 및 힙 사용?

lottogame 2020. 7. 12. 09:45
반응형

C ++에서 적절한 스택 및 힙 사용?


한동안 프로그래밍을 해왔지만 주로 Java와 C #이었습니다. 실제로 실제로 메모리를 관리 할 필요는 없었습니다. 나는 최근에 C ++로 프로그래밍을 시작했으며 스택에 물건을 저장 해야하는 시점과 힙에 저장하는 시점에 대해 약간 혼란 스럽습니다.

매우 자주 액세스하는 변수는 스택에 저장해야하며 거의 사용되지 않는 변수 및 큰 데이터 구조는 모두 힙에 저장해야합니다. 이것이 맞습니까, 아니면 맞습니까?


아니요, 스택과 힙의 차이는 성능이 아닙니다. 수명 : 함수 내부의 모든 로컬 변수 (malloc () 또는 new가 아닌 ​​것)는 스택에 있습니다. 함수에서 돌아 오면 사라집니다. 선언 한 함수보다 오래 살려면 힙에 할당해야합니다.

class Thingy;

Thingy* foo( ) 
{
  int a; // this int lives on the stack
  Thingy B; // this thingy lives on the stack and will be deleted when we return from foo
  Thingy *pointerToB = &B; // this points to an address on the stack
  Thingy *pointerToC = new Thingy(); // this makes a Thingy on the heap.
                                     // pointerToC contains its address.

  // this is safe: C lives on the heap and outlives foo().
  // Whoever you pass this to must remember to delete it!
  return pointerToC;

  // this is NOT SAFE: B lives on the stack and will be deleted when foo() returns. 
  // whoever uses this returned pointer will probably cause a crash!
  return pointerToB;
}

스택이 무엇인지 더 명확하게 이해하려면 스택에서 다른 언어를 사용하십시오. 스택이 고급 언어 측면에서 무엇을하는지 이해하기보다는 "호출 스택"및 "호출 규칙"을 찾아서 기계는 실제로 함수를 호출 할 때 수행합니다. 컴퓨터 메모리는 일련의 주소 일뿐입니다. "힙"과 "스택"은 컴파일러의 발명품입니다.


내가 말할 것:

가능하면 스택에 보관하십시오.

필요한 경우 힙에 저장하십시오.

따라서 힙보다 스택을 선호합니다. 스택에 무언가를 저장할 수없는 몇 가지 이유는 다음과 같습니다.

  • 32 비트 OS의 다중 스레드 프로그램에서 스택은 작고 고정 된 (최소 스레드 작성 시간에) 크기 (일반적으로 몇 메가)에 불과하므로 주소를 소진하지 않고 많은 스레드를 작성할 수 있습니다. 64 비트 프로그램 또는 단일 스레드 (Linux 어쨌든) 프로그램의 경우 이는 큰 문제가되지 않습니다 .32 비트 Linux에서 단일 스레드 프로그램은 일반적으로 동적 스택을 사용하여 힙의 맨 위에 도달 할 때까지 계속 증가합니다.
  • 원래 스택 프레임 범위 밖에서 액세스해야합니다. 이것이 주된 이유입니다.

합리적인 컴파일러의 경우 고정되지 않은 크기의 객체를 힙 (일반적으로 컴파일시 크기를 알 수없는 배열)에 할당 할 수 있습니다.


다른 답변이 제안하는 것보다 미묘합니다. 스택의 데이터와 힙의 데이터는 선언 방법에 따라 절대로 나누지 않습니다. 예를 들면 다음과 같습니다.

std::vector<int> v(10);

함수 본문 vector에서 스택에 10 개의 정수로 구성된 (동적 배열) 을 선언합니다 . 그러나에 의해 관리되는 스토리지 vector는 스택에 없습니다.

아, 그러나 (다른 답변은 제안합니다) 스토리지의 수명 vector은 스택 수명 인 자체 수명에 의해 제한 되므로 구현 방식에 차이가 없습니다. 스택 기반 객체로만 처리 할 수 ​​있습니다. 가치 의미론으로.

별로. 기능이 다음과 같다고 가정하십시오.

void GetSomeNumbers(std::vector<int> &result)
{
    std::vector<int> v(10);

    // fill v with numbers

    result.swap(v);
}

따라서 swap함수 (및 복잡한 값 유형이 있어야 함)가있는 모든 것은 해당 데이터의 단일 소유자를 보장하는 시스템에서 일부 힙 데이터에 대한 일종의 리 바인드 가능한 참조 역할을 할 수 있습니다.

따라서 최신 C ++ 방식은 힙 데이터의 주소를 네이 키 로컬 포인터 변수에 저장 하지 않는 것 입니다. 모든 힙 할당은 클래스 내에서 숨겨져 야합니다.

그렇게하면 프로그램의 모든 변수가 단순한 값 유형 인 것처럼 생각하고 힙을 모두 잊어 버릴 수 있습니다 (일부 힙 데이터에 대해 새로운 값과 같은 래퍼 클래스를 작성할 때는 예외입니다) .

가능한 한 하나의 변수를 다음과 같이 다른 변수에 할당하는 대신 최적화하는 데 도움이되는 하나의 특별한 지식 만 유지하면됩니다.

a = b;

다음과 같이 바꾸십시오 :

a.swap(b);

because it's much faster and it doesn't throw exceptions. The only requirement is that you don't need b to continue to hold the same value (it's going to get a's value instead, which would be trashed in a = b).

The downside is that this approach forces you to return values from functions via output parameters instead of the actual return value. But they're fixing that in C++0x with rvalue references.

In the most complicated situations of all, you would take this idea to the general extreme and use a smart pointer class such as shared_ptr which is already in tr1. (Although I'd argue that if you seem to need it, you've possibly moved outside Standard C++'s sweet spot of applicability.)


You also would store an item on the heap if it needs to be used outside the scope of the function in which it is created. One idiom used with stack objects is called RAII - this involves using the stack based object as a wrapper for a resource, when the object is destroyed, the resource would be cleaned up. Stack based objects are easier to keep track of when you might be throwing exceptions - you don't need to concern yourself with deleting a heap based object in an exception handler. This is why raw pointers are not normally used in modern C++, you would use a smart pointer which can be a stack based wrapper for a raw pointer to a heap based object.


To add to the other answers, it can also be about performance, at least a little bit. Not that you should worry about this unless it's relevant for you, but:

Allocating in the heap requires finding a tracking a block of memory, which is not a constant-time operation (and takes some cycles and overhead). This can get slower as memory becomes fragmented, and/or you're getting close to using 100% of your address space. On the other hand, stack allocations are constant-time, basically "free" operations.

Another thing to consider (again, really only important if it becomes an issue) is that typically the stack size is fixed, and can be much lower than the heap size. So if you're allocating large objects or many small objects, you probably want to use the heap; if you run out of stack space, the runtime will throw the site titular exception. Not usually a big deal, but another thing to consider.


Stack is more efficient, and easier to managed scoped data.

But heap should be used for anything larger than a few KB (it's easy in C++, just create a boost::scoped_ptr on the stack to hold a pointer to the allocated memory).

Consider a recursive algorithm that keeps calling into itself. It's Very hard to limit and or guess the total stack usage! Whereas on the heap, the allocator (malloc() or new) can indicate out-of-memory by returning NULL or throw ing.

Source: Linux Kernel whose stack is no larger than 8KB!


For completeness, you may read Miro Samek's article about the problems of using the heap in the context of embedded software.

A Heap of Problems


The choice of whether to allocate on the heap or on the stack is one that is made for you, depending on how your variable is allocated. If you allocate something dynamically, using a "new" call, you are allocating from the heap. If you allocate something as a global variable, or as a parameter in a function it is allocated on the stack.


In my opinion there are two deciding factors

1) Scope of variable
2) Performance.

I would prefer to use stack in most cases but if you need access to variable outside scope you can use heap.

To enhance performance while using heaps you can also use the functionality to create heap block and that can help in gaining performance rather than allocating each variable in different memory location.


probably this has been answered quite well. I would like to point you to the below series of articles to have a deeper understanding of low level details. Alex Darby has a series of articles, where he walks you through with a debugger. Here is Part 3 about the Stack. http://www.altdevblogaday.com/2011/12/14/c-c-low-level-curriculum-part-3-the-stack/

참고URL : https://stackoverflow.com/questions/599308/proper-stack-and-heap-usage-in-c

반응형