2012-01-23 3 views
4

나는 그것은 다음과 같습니다 ... 유래를 생산할 수있을 것 같지 않는 코드의 세그먼트에 대한 스택 오버 플로우 예외를 받고 있어요 : 더 재귀 호출이 없습니다 재귀 때문에 스택 오버플로가 발생할 수 있습니까?

public String WriteToFile(XmlDocument pDoc, String pPath) 
{ 
    string source = ""; 
    string seq = ""; 
    string sourcenet = ""; 

    XmlNodelist sourceNode = pDoc.GetElementsByTagName(XmlUtils.Nodes.Source); 
    source = sourceNode.Item(0).InnerText; 

    XmlNodelist sqList= pDoc.GetElementsByTagName(XmlUtils.Nodes.Seq); 
    seq = sqList.Item(0).InnerText; 

    XmlNodelist sourceNets = pDoc.GetElementsByTagName(XmlUtils.Nodes.SourceNets); 
    sourcenet = sourceNets.Item(0).InnerText; 

    string fileName = Folders.GetMyFileName(source, seq, sourcenet); 
    string fullPath = Path.Combine(pPath, fileName); 

    pDoc.Save(pFullPathFile); <--- Stackoverflow is raised here 

    return pFullPathFile; 
} 

당신이 경우 "외부 코드"로 이동하기 전에 깊이가 2 인 호출 스택을 조사하십시오 (디버깅이 해제 된 스레드를 시작하는 프레임 워크의 일부분이지만 외부적인 것이 아닙니다).

어쨌든 재귀 호출 이외의 다른 예외가 발생할 수 있습니까? 그것은 항상 pDoc.Save 메서드 호출에서 실패합니다 ... 그리고 pDoc은 실제로 그렇게 크지 않습니다 ... 32KB의 데이터와 더 비슷합니다 ...

+0

실제 코드를 게시 할 수 있습니까? 이 코드에서 pFullPathFile이 어디서 발생하는지 알지 못합니다. – Joe

답변

7

스택 오버 플로우 예외는 스택이 초과 할 때마다 발생할 수 있습니다 최대 크기. 이것은 주로 일반적으로 다음과 같이 수행됩니다.

  • 재귀 적이 아닌 깊이 중첩 된 스택이 있습니다. 이벤트 A가 이벤트 B로 연결되는 이벤트 폭풍을 생각해보십시오. 이벤트 B는 모두 스택을 깊이 자라는 핸들러를 가지고 있습니다.
4

스택 오버 플로우가 단순히 스택을 소진 의미 ​​일부 대형 스택 할당 후 발생하는 얕은 스택을 갖는, 그것은 재귀에 의해 야기 될 필요가 없습니다. 물론 재귀는 스택을 사용하기 때문에 종종 스택 오버플로 예외의 원인이되지만 필요하지는 않습니다.

제공된 정보에 따르면 제공된 코드에 스택 오버플로가 발생할 수있는 것처럼 보이지 않습니다.

기본적으로 C#의 스레드에는 1MB 스택이 있지만, 사용자는 create a new thread with a smaller stack이 될 수 있습니다. 이 프로그램에서 직접 스레드를 생성하고 스택 크기를 설정합니까?

또한 외부 코드 섹션을보십시오 (Call Stack 윈도우의 External Code를 오른쪽 클릭하고 "Show external code"를 선택하십시오). 무언가가 잘못 보이는지 확인하십시오. 어떤 이유로 프레임 워크가 저장을 수행하기 위해 많은 메소드 호출을 수행합니까?

+0

ASP.NET의 기본값이 다릅니다. –

0

일부 언어/런타임에서 스택 오버플로 이 호출 스택 자체와 관련이없는 큰 메모리 할당으로 인해 발생할 수 있습니다. 그것은 '외부 코드'(전 프레임 워크를 가정)가 그 상황으로 돌입하거나 실제로 볼 수없는 고전적인 재귀 오버 플로우 문제를 가지고있을 가능성이 있습니다. 왜냐하면 반드시 디버깅 할 수 없기 때문입니다.

2

참으로 재귀 호출이 있습니다.

pDoc.Save()WriteContentTo(XmlWriter w)을 호출하는 문서의 WriteTo(XmlWriter w)을 호출합니다.

이 다음 하나 개의 요소 노드를 포함 할 루트 수준에서 모든 노드에 WriteTo(XmlWriter w) 호출 (아마도 일부 의견, 공백, 처리 명령, 문서 declarataion ...).

해당 요소에

, 이것은 그것의 태그를 작성하는 원인이됩니다 ('<', 요소 이름을 입력 한 다음, 속성) 등 등 WriteContentTo(XmlWriter w)를 호출하는 모든 자식 요소에 WriteTo(XmlWriter w)를 호출 WriteContentTo(XmlWriter w)를 호출하고, 다음 에.

따라서 실제로는 각 요소가 하위 요소에서 동일한 메서드를 호출하고 충분히 작은 스택 공간 (기본값은 대부분 응용 프로그램에서는 1MB이지만 ASP.NET에서는 256KB)에서 충분히 깊은 문서로 호출하는 경우 재귀 적입니다. 스택 오버 플로우가 발생합니다.

레코드의 경우 스택 공간을 비 롯하는 한 재귀없이 스택 오버플로를 가질 수도 있습니다. stackalloc은 전화를 몇 번만하면서이 작업을 수행 할 수있는 좋은 방법입니다. 이 때문에이 재귀에 문제가 있다면

, 다음 WriteTo의 구현은 기본적으로 (수동으로 WriteContentTo를 인라인)임을 기억

w.WriteStartElement(this.Prefix, this.LocalName, this.NamespaceURI); 
if (this.HasAttributes) 
{ 
    XmlAttributeCollection attributes = this.Attributes; 
    for (int i = 0; i < attributes.Count; i++) 
    { 
     attributes[i].WriteTo(w); 
    } 
} 
if (this.IsEmpty) 
{ 
    w.WriteEndElement(); 
} 
else 
{ 
    for (XmlNode node = this.FirstChild; node != null; node = node.NextSibling) 
    { 
    node.WriteTo(w); 
    } 
    w.WriteFullEndElement(); 
} 

가 반복 버전이 교체, 당신은 '원 스택 오버플로. 물론 당신이 어떻게 든 문서를 자신에게 조상 인 요소가있는 상태로 만들었다면 (XmlDocument가 그것을 보호합니까? 나는 머리의 꼭대기에서 알지 못합니다), 그러면 돌아갑니다 무한 루프로의 스택 오버플로.

관련 문제