2011-07-01 2 views
3

this tutorial을 읽고 this question을 읽었습니다. 내 질문은 다음과 같습니다.C++ 일부 스택 질문

  1. 스택의 크기는 얼마나됩니까? 그것이 프로세서/아키텍처/컴파일러 에 종속 되나요?

  2. 많은 메모리 내 기능/클래스 스택을 사용할 수 있습니다 얼마나 많은 현재 피할 오버 플로우하기 위해 사용되는 방법을 정확하게 알 수있는 방법이 있나요?

  3. 사용하여 현대적인 컴파일러 현대 컴퓨터 (예를 들어 6기가바이트 램), (예를 들어 4.5 GCC) 내가 스택 오버 플로우에 대해 걱정할 필요하거나이 과거의 일이 무엇입니까?

  4. RAM 또는 CPU 캐시에 실제로 스택 메모리 이 있습니까?

  5. 스택 메모리가 얼마나 더 빠릅니까 힙에 액세스하고 읽음이 액세스 및 읽기보다 빠릅니다. 나는 번이 PC마다 다르다는 것을 알기 때문에, 비율은 정도로 충분합니다.

  6. 나는 스택에 큰 vars/개체를 할당하는 것이 좋지 않다는 것을 읽었습니다. 얼마가 너무 큽니까? This question here은 win32의 스레드에 대해 1MB의 대답 이 주어집니다. 어떻게 리눅스 amd64에서 스레드에 대한 ?

이러한 질문에 답변하고 이미 답변 한 경우 사과드립니다. 어떤 링크를 환영합니다!

+4

이것은 좀 더 집중된 질문으로 나눌 수 있다고 생각합니다. –

+0

단일 답변에서 다루기에는 너무 광범위합니다. 실제로는 10 개의 완전히 별개의 질문입니다. – littleadv

+0

어떻게해야합니까? 몇 가지 질문을하고 다른 실에서 질문하십시오. –

답변

8
  1. 예, 스택 크기에 대한 제한은 다양하지만, 당신이 걱정하는 경우가 뭔가 잘못하고 아마입니다.
  2. 일반적으로 프로그램에서 사용할 수있는 메모리 양에 대한 정보를 얻을 수 없습니다. 그러한 정보를 얻을 수 있다고해도, 일반적으로 사용하기 전에 오래 가지 못합니다.
  3. 스레드간에 데이터에 대한 액세스를 공유하는 경우 일반적으로 읽기 전용이 아닌 경우 일반적으로 액세스를 직렬화해야합니다.
  4. 스택 할당 객체의 주소를 다른 스레드로 전달할 수 있습니다.이 경우 액세스가 엄격하게 읽기 전용이 아닌 경우 직렬화해야합니다.
  5. 많은 메모리가있는 최신 기계에서도 스택을 오버플로 할 수 있습니다. 스택은 전체 메모리의 아주 작은 부분 (예 : 4MB)으로 제한되는 경우가 많습니다.
  6. 스택은 시스템 메모리로 할당되지만 대개 적어도 상단 페이지 또는 두 개가 대개 지정된 시간에 캐시에있을 정도로 충분히 사용됩니다.
  7. 스택 대 힙 (heap)의 일부분은 액세스 속도와 직접적인 차이가 없습니다. 일반적으로이 두 메모리는 동일한 메모리 칩에 있으며 대개 동일한 메모리 칩의 다른 주소에도 있습니다. 가장 큰 차이점은 스택이 일반적으로 연속적이며 많이 사용된다는 것인데, 상위 몇 페이지가 거의 항상 캐시에있게됩니다. 힙 기반 메모리는 일반적으로 조각화되어 있으므로 캐시에없는 데이터를 필요로 할 확률이 훨씬 높습니다.
  8. 스택에 할당해야하는 객체의 최대 크기와 관련하여 거의 변경되지 않았습니다. 스택이 일 수 있더라도이 더 클 수 있습니다. 거대한 개체를 할당 할 이유가 거의 없습니다.
  9. C++에서 메모리 누수를 피하는 주요 방법은 RAII (일명 SBRM, 스택 기반 리소스 관리)입니다.
  10. 스마트 포인터는 그 자체로 큰 주제이며, Boost는 여러 종류를 제공합니다. 필자의 경험에 따르면, 콜렉션은 더 큰 차이를 만들지 만, 기본적인 아이디어는 대체로 같은 방식이다 : 프로그래머가 특정 객체를 사용할 수 있거나 해제해야하는 모든 상황을 파악하는 것을 완화하라.
+0

마지막 질문이 생겼습니다. 클래스 멤버 변수는 기본적으로 할당되어 있습니까? (스택이나 힙에 있다고 지정하지 않았다고 가정). 내 질문에 답변 해 주셔서 감사합니다. –

+1

@Alex : 정적 멤버가 정적으로 할당됩니다 (큰 놀라움). 그렇지 않으면 클래스를 정의하는 방법이 아니라 개체를 할당하는 방법에 따라 다릅니다. –

+1

@Alex 멤버는 개체가 저장된 곳이면 어디에나 저장됩니다. 'class Foo {Bar b; }'스택에'Foo'를 넣으면'Bar'가 스택에 놓이게됩니다. –

2

1-2 : 일부 내장 CPU에서는 스택이 몇 KB로 제한 될 수 있습니다. 일부 컴퓨터에서는 기가 바이트로 확장 될 수 있습니다. 일부 플랫폼은 스택에 한계에 도달했을 때 스택을 확장 할 수 있기 때문에 어떤 방법으로 스택의 크기를 알 수있는 플랫폼 독립적 인 방법은 없습니다. 그러한 조작의 성공이 항상 미리 예측 될 수는 없다.

3 : 거의 동시 쓰기 또는 다른 스레드의 읽기와 거의 동시에 발생하는 한 스레드의 쓰기의 영향은 잠금, 뮤텍스 또는 다른 장치가없는 경우 크게 예측할 수 없습니다. 어떤 것들이 가정 될 수 있습니다 (예를 들어, 한 스레드가 힙을 저장 한 'int'를 읽는 동안 다른 스레드가 스레드를 4에서 5로 변경하면 첫 번째 스레드는 4를 보거나 5를 볼 수 있습니다.) 대부분의 플랫폼에서는 보장됩니다 27).

4 : 일부 플랫폼은 스레드간에 스택 주소 공간을 공유합니다. 다른 사람들은 그렇지 않습니다. 포인터를받는 외부 스레드가 대상이 범위에 있고 범위를 벗어나지 않도록 보장 할 방법이 없기 때문에 스택에있는 항목에 포인터를 전달하는 것은 일반적으로 나쁜 생각입니다.

5 일반적으로 재귀를 합리적인 수준으로 제한하기 위해 작성된 루틴에서는 스택 공간에 대해 걱정할 필요가 없습니다. 그러나 무한 재귀를 초래하는 결함있는 데이터 구조의 가능성에 대해 걱정할 필요가 있습니다. 무한 재귀는 아무리 큰 경우에도 스택을 없앨 수 있습니다. 예상보다 훨씬 더 큰 스택 깊이를 야기 할 수있는 불쾌한 입력 가능성에 유의해야합니다. 예를 들어, 재귀 - 하강 파서 (parser)를 사용하는 컴파일러는 "1+"시퀀스의 10 억 반복을 포함하는 파일이 제공되면 초크가 발생할 수 있습니다. 시스템에 스택 공간이 있어도 중첩 된 각 하위 표현식이 64 바이트를 사용하면 스택은 일반적으로 RAM 및/또는 캐시에 저장되며 가장 최근에 액세스 한 부분은 일반적으로 캐시에 저장되는 반면 최근에 액세스 한 부분은 캐시에 저장됩니다. 일반적으로 코드, 힙 및 정적 저장 영역에 대해서도 마찬가지입니다.

7 : 이는 시스템에 매우 의존적이므로 일반적으로 힙에서 "찾는"작업에는 많은 시간이 소요됩니다 스택에있는 몇 가지 항목에 액세스하는 것처럼 보이지만, 많은 경우 동일한 항목의 여러 부분에 여러 번 액세스합니다. ap 객체는 스택 객체에 액세스하는 것만큼 빠릅니다.

3

1. 스택은 얼마나 커질 수 있습니까? 프로세서/아키텍처/컴파일러에 종속적입니까?

스택의 크기는 플랫폼 운영 체제 프로세스에 할당 된 메모리에 메모리의 양에 의해 제한된다.

2. 함수/클래스 스택에서 사용할 수있는 메모리의 양과 오버플로를 방지하기 위해 현재 사용중인 메모리 양을 정확하게 알 수있는 방법이 있습니까?

사용 가능한 메모리 양을 결정하는 C 또는 C++ 기능은 없습니다. 이를위한 플랫폼 특정 기능이있을 수 있습니다. 일반적으로 대부분의 프로그램은 메모리 할당을 시도한 다음 할당 실패시 해결 방법을 제안합니다.

3. 최신 컴퓨터 (예 : 6GB RAM)에서 현대 컴파일러 (예 : gcc 4.5)를 사용하면 스택 오버플로가 걱정 되나요? 아니면 과거의 일입니까?

스택 오버플로는 프로그램의 디자인에 따라 발생할 수 있습니다. 재귀는 메모리 양에 관계없이 스택을 고갈시키는 좋은 예입니다.

실제 RAM 또는 CPU 캐시에 실제 스택 메모리가 있습니까?

플랫폼에 따라 다릅니다. 일부 CPU는 스택의 로컬 변수를 사용하여 캐시를로드 할 수 있습니다. 이 주제에 대한 다양한 시나리오. 언어 사양에 정의되지 않았습니다.

5. 스택 메모리 액세스 및 읽기 속도가 힙 액세스 및 읽기 속도보다 빨라 집니까?
시간은 PC에 따라 다르므로 비율은 충분합니다.

전체적으로 속도에는 차이가 없습니다. 플랫폼이 메모리를 (물리적으로) 구성하는 방법과 실행 파일의 메모리가 배치되는 방법에 따라 다릅니다. 힙 또는 스택은 직렬 액세스 메모리 칩 (느린 방법) 또는 플래시 메모리 칩에 상주 할 수 있습니다. 언어 사양에 지정되지 않았습니다.

6. 큰 용기/개체를 스택에 할당하는 것은 좋지 않다고 읽었습니다. 얼마가 너무 큽니까? 이 질문은 win32에서 쓰레드에 대한 1MB의 답이 주어진다. Linux amd64의 스레드는 어떻습니까?

가장 좋은 조언은 필요에 따라 로컬 작은 변수를 할당하는 것입니다 (스택을 통해 a.k.a.). 거대한 항목은 동적 메모리 (a.k.a 힙) 또는 일종의 전역 변수 (정적 로컬 함수 또는 로컬 변환 단위 또는 전역 변수) 중 하나입니다. 컴파일 타임에 크기를 알고 있으면 전역 유형 할당을 사용하십시오. 런타임 동안 크기가 변경 될 수있는 경우 동적 메모리를 사용하십시오.

스택에는 함수 주소에 대한 정보도 들어 있습니다. 이것이 많은 객체를 로컬에 할당하지 않는 주된 이유 중 하나입니다. 일부 컴파일러는 힙 또는 전역 변수보다 스택에 대한 제한이 더 적습니다. 전제는 중첩 된 함수 호출이 대형 데이터 배열이나 버퍼보다 ​​적은 메모리를 필요로한다는 것입니다.

스레드 또는 작업을 전환 할 때 OS가 상태를 어딘가에 저장해야한다는 것을 기억하십시오. OS는 스택 메모리를 다른 유형과 비교하여 저장하기위한 다른 규칙을 가질 수 있습니다.