Can stack overflow happen for any other reason related to recursion?

I get an exception for a code segment that seems to be unable to create stackoverflow ... It looks like this:

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; } 

There are no recursive calls, if you examine the call stack, it has a depth of 2 before moving on to the “external code” (which, I assume, is not external, but part of the framework that starts the thread that has debugging is turned off).

¿In any case, an exception can be raised because there is nothing but a recursive call? It ALWAYS fails in calling the pDoc.Save method ... and pDoc is actually not that big ... more like 32 Kbytes of data ...

+4
source share
4 answers

An exception may occur at any time when the stack exceeds the maximum size. This is usually done using ...

  • Having a deeply nested stack that is not recursive. Think of event storms when event A leads to event B, which leads to event C, in which there are handlers that deeply expand the stack.
  • The presence of a shallow stack that occurs after some large stack distributions
+7
source

Stack overflow simply means that you have run out of stack, this should not be caused by recursion. Of course, since recursion uses the stack, this is often the cause of the exception, but it is not necessary.

At the same time, with the information you provided, it does not look like something should happen in the code that you specified, causing a stack overflow.

Threads in C # by default have a 1 MB stack, but you can create a new thread with a smaller stack . Do you create themes in this program and set the stack size?

Also, look at the external section of the code (right-click where it says “External Code” in the “Call Stack” window, select “Show External Code”). Look, something looks wrong, is some kind of framework some reason that goes through a lot of method calls to save?

+4
source

There is a truly recursive call.

pDoc.Save() calls WriteTo(XmlWriter w) in the document, which calls WriteContentTo(XmlWriter w) .

Then it calls WriteTo(XmlWriter w) on all nodes of the root level, which will contain one node element (maybe also some comments, spaces, processing instructions, document declaration ...).

In this element, this will cause it to write its tag ('<', the name of the element, and then any attributes), and then call WriteContentTo(XmlWriter w) , which calls WriteTo(XmlWriter w) for each child element that calls WriteContentTo(XmlWriter w) , etc. etc.

Therefore, this is really recursive in the way each element calls the same method for its children and with a sufficiently deep document on a fairly small stack space (by default, most applications use 1 MB, but 256 KB on ASP.NET) Overflow stack.

For the record, you can also have stack overflow without recursion if you somehow drive the stack space. stackalloc is a great way to find yourself by making just a few calls.

If you are having problems due to this recursion, remember that the WriteTo implementation is essentially (manually inserting WriteContentTo into it):

 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(); } 

Replace it with the iterative version and you won’t overflow the stack. Of course, if you managed to somehow bring the document to a state where it received an element that is an ancestor of itself (does XmlDocument protect against this? I don’t know, from my point of view), then it will turn the stack overflow into an infinite loop, which if something is worse.

+2
source

In some languages ​​/ runtime, stack overflows may occur due to large memory allocations that are not related to the call stack itself. It is possible that the "external code" (I assume that the framework) works either in this situation, or in fact is a problem of overflowing classical recursion, which you do not see because you cannot debug it.

0
source

Source: https://habr.com/ru/post/1392506/


All Articles