문제

스택 오버 플로우는 어떻게 발생하고 발생하지 않도록하는 가장 좋은 방법은 무엇이며 특히 웹 서버에서이를 방지하는 방법은 무엇입니까?하지만 다른 예도 흥미로울까요?

도움이 되었습니까?

해결책

스택

이 맥락에서 스택은 프로그램이 실행되는 동안 데이터를 배치하는 마지막 in, first out 버퍼입니다. LIFO (Last in, First Out)는 마지막에 넣은 것이 항상 가장 먼저 다시 나오는 것을 의미합니다. 스택에 2 개의 항목 ( 'A', 'B'를 차례로 밀어 넣으면 가장 먼저 터지는 것) 스택에서 'B'가되고 다음은 'A'입니다.

코드에서 함수를 호출하면 함수 호출 후 다음 명령어가 스택에 저장되고 함수 호출로 덮어 쓸 수있는 모든 저장 공간이 저장됩니다. 호출하는 함수는 자체 지역 변수에 대해 더 많은 스택을 사용할 수 있습니다. 완료되면 사용한 로컬 변수 스택 공간을 확보 한 다음 이전 함수로 돌아갑니다.

스택 오버플로

스택 오버플로는 프로그램에서 사용하는 것보다 더 많은 메모리를 스택에 사용했을 때 발생합니다. 임베디드 시스템에서는 스택에 256 바이트 만있을 수 있으며 각 함수가 32 바이트를 차지하면 함수 호출 8 개만 가질 수 있습니다. 함수 1은 함수 4를 호출하는 함수 3을 호출하는 함수 2를 호출합니다. 함수 9를 호출하는 함수 8이지만 함수 9는 스택 외부의 메모리를 덮어 씁니다. 메모리, 코드 등을 덮어 쓸 수 있습니다.

많은 프로그래머가 함수 A를 호출 한 다음 함수 B를 호출 한 다음 함수 C를 호출 한 다음 함수 A를 호출함으로써 이러한 실수를 저지 릅니다. 대부분의 경우 작동 할 수 있지만 잘못된 입력으로 인해 입력이 시작됩니다. 컴퓨터가 스택이 과장된 것을 인식 할 때까지 그 원은 영원히.

재귀 함수도 이에 대한 원인이지만, 재귀 적으로 작성하는 경우 (즉, 함수 자체 호출)이를 인식하고 정적 / 전역 변수를 사용하여 무한 재귀를 방지해야합니다.

일반적으로 사용중인 OS와 프로그래밍 언어가 스택을 관리하며 손이 닿지 않습니다. 함수 호출의 깊이를 확인하고 의도하지 않은 순환과 재귀를 감지하려면 호출 그래프 (각 함수가 호출하는 내용을 메인에서 보여주는 트리 구조)를 살펴 봐야합니다. 의도적 인 순환과 재귀는 서로를 너무 많이 호출하면 오류가 발생하도록 인위적으로 검사해야합니다.

좋은 프로그래밍 관행, 정적 및 동적 테스트 외에 이러한 고급 시스템에서 할 수있는 일은 많지 않습니다.

내장형 시스템

임베디드 세계, 특히 고 신뢰성 코드 (자동차, 항공기, 우주)에서 광범위한 코드 검토 및 검사를 수행하지만 다음 작업도 수행합니다.

  • 재귀 및주기 금지-정책 및 테스트에 의해 시행
  • 코드와 스택을 멀리 떨어 뜨려 놓으십시오 (코드는 플래시에, 스택은 RAM에, 두 사람이 만나지 않아야합니다)
  • 스택 주위에 가드 밴드를 배치합니다. 메모리의 빈 영역을 매직 넘버 (일반적으로 소프트웨어 인터럽트 명령이지만 여기에는 많은 옵션이 있음)로 채우고 가드 밴드를 1 초에 수백 또는 수천 번 봅니다. 덮어 쓰지 않았는지 확인합니다.
  • 메모리 보호 사용 (즉, 스택에서 실행 안 함, 스택 외부에서 읽기 또는 쓰기 금지)
  • 인터럽트는 2 차 함수를 호출하지 않습니다. 플래그를 설정하고, 데이터를 복사하고, 애플리케이션이 처리하도록합니다 (그렇지 않으면 함수 호출 트리에 8 개 깊이가 들어가고 인터럽트가 발생한 다음 몇 개 더 나가게됩니다. 인터럽트 내부의 기능으로 인해 폭발이 발생합니다). 여러 호출 트리가 있습니다. 하나는 기본 프로세스 용이고 하나는 각 인터럽트 용입니다. 끼어 들기가 서로 끼어들 수 있다면 ... 글쎄요, 드래곤이 있습니다 ...

    고급 언어 및 시스템

    하지만 고급 언어에서는 운영 체제에서 실행됩니다.

    • 로컬 변수 저장소를 줄입니다 (로컬 변수는 스택에 저장됩니다. 컴파일러는 이에 대해 꽤 똑똑하고 호출 트리가 얕은 경우 힙에 큰 로컬을 배치하기도합니다)

또는 엄격하게 재귀 제한
  • 프로그램을 더 작고 작은 함수로 너무 많이 나누지 마십시오. 지역 변수를 계산하지 않아도 각 함수 호출은 스택에서 64 바이트를 소비합니다 (32 비트 프로세서, CPU 레지스터, 플래그 등의 절반 절약).
  • 위의 설명과 유사하게 호출 트리를 얕게 유지

    웹 서버

    스택을 제어하거나 볼 수 있는지 여부는 보유한 '샌드 박스'에 따라 다릅니다.웹 서버를 다른 높은 수준의 언어 및 운영 체제처럼 취급 할 수있는 가능성이 높습니다. 대부분 손에서 벗어 났지만 사용중인 언어와 서버 스택을 확인하십시오.예를 들어 SQL 서버에서 스택을 날려 버릴 수 있습니다 .

    -아담

  • 다른 팁

    실제 코드에서 스택 오버플로는 거의 발생하지 않습니다.그것이 발생하는 대부분의 상황은 종료가 잊혀진 재귀입니다.그러나 고도로 중첩 된 구조에서는 거의 발생하지 않을 수 있습니다.특히 큰 XML 문서.여기서 유일한 도움은 호출 스택 대신 명시 적 스택 객체를 사용하도록 코드를 리팩터링하는 것입니다.

    대부분의 사람들은 종료 경로가없는 재귀로 스택 오버플로가 발생한다고 말할 것입니다. 대부분 사실이지만 충분한 데이터 구조로 작업하는 경우 적절한 재귀 종료 경로도 도움이되지 않습니다.

    이 경우 일부 옵션 :

    무한 재귀는 스택 오버플로 오류를 얻는 일반적인 방법입니다.방지하려면-항상 명중 할 출구 경로가 있는지 확인하십시오.:-)

    스택 오버플로를 얻는 또 다른 방법 (적어도 C / C ++에서)은 스택에 엄청난 변수를 선언하는 것입니다. 라코 디스

    그렇습니다.

    Jeff와 Joel이 기술적 인 질문에 대한 답을 얻을 수있는 더 나은 장소를 제공하고자 할 때 스택 오버플로가 발생합니다.이 스택 오버플로를 방지하기에는 너무 늦었습니다.그 "다른 사이트"는 은밀하지 않음으로써이를 막을 수있었습니다.;)

    일반적으로 스택 오버플로는 무한 재귀 호출의 결과입니다 (요즘 표준 컴퓨터의 일반적인 메모리 양을 고려할 때).

    메서드, 함수 또는 프로 시저를 호출 할 때 "표준"방식 또는 호출은 다음으로 구성됩니다.

    1. 호출 방향을 스택으로 푸시 (호출 후 다음 문장)
    2. 보통 반환 값을위한 공간은 스택에 예약됩니다.
    3. 각 매개 변수를 스택으로 푸시 (순서는 각 컴파일러에 따라 다르며 일부는 성능 향상을 위해 CPU 레지스터에 저장되기도합니다)
    4. 실제 전화 걸기

      일반적으로이 작업은 매개 변수의 수와 유형 및 머신 아키텍처에 따라 몇 바이트가 걸립니다.

      그러면 재귀 호출을 시작하면 스택이 커지기 시작한다는 것을 알 수 있습니다. 이제 스택은 일반적으로 힙과 반대 방향으로 증가하는 방식으로 메모리에 예약되어 있으므로 "돌아 오지 않는"많은 호출이 주어지면 스택이 가득 차기 시작합니다.

      이제 예전에는 사용 가능한 모든 메모리를 소진했기 때문에 스택 오버플로가 발생할 수 있습니다. 범위를 벗어난 가상 메모리 모델 (X86 시스템에서 최대 4GB)의 경우 일반적으로 스택 오버플로 오류가 발생하면 무한 재귀 호출을 찾습니다.

    직접 재귀 (예 : Fibonacci(1000000))에서 얻을 수있는 스택 오버플로의 형태를 제외하고, 제가 여러 번 경험 한보다 미묘한 형태는 간접 재귀입니다. 여기서 함수는 다른 함수를 호출하는 다른 함수를 호출합니다.그런 다음 이러한 함수 중 하나가 첫 번째 함수를 다시 호출합니다.

    이는 일반적으로 이벤트에 대한 응답으로 호출되지만 자체적으로 새 이벤트를 생성 할 수있는 함수에서 발생할 수 있습니다. 예를 들면 다음과 같습니다. 라코 디스

    이 경우 ResizeWindow에 대한 호출로 인해 WindowSizeChanged() 콜백이 다시 트리거되어 스택이 부족해질 때까지 ResizeWindow를 다시 호출 할 수 있습니다.이와 같은 상황에서는 메시지를 게시하는 등 스택 프레임이 반환 될 때까지 이벤트에 대한 응답을 연기해야하는 경우가 많습니다.

    뭐라고 요?아무도 무한 루프로 인해 발생하는 것을 좋아하지 않습니까? 라코 디스

    이 태그가 "해킹"이라는 점을 고려할 때, 그가 언급 한 "스택 오버플로"는 여기에있는 대부분의 다른 답변에서 참조 된 것과 같은 상위 수준 스택 오버플로가 아니라 호출 스택 오버플로라고 생각합니다.웹 앱이 일반적으로 작성되는 .NET, Java, Python, Perl, PHP 등과 같은 관리 또는 해석 환경에는 실제로 적용되지 않으므로 유일한 위험은 웹 서버 자체입니다.C 또는 C ++.

    이 스레드 확인 :

    https://stackoverflow.com/questions/7308/what-is-a-학습 버퍼 오버플로를위한 좋은 시작점

    라이센스 : CC-BY-SA ~와 함께 속성
    제휴하지 않습니다 StackOverflow
    scroll top