4 Replies Latest reply: Aug 24, 2012 7:17 AM by Graham vdR RSS

    Stack overrun

    Graham vdR Community Member

      Hi

       

      I’m working on a script that reads a text file, creates objects from tags it finds using a recursive function, pushes these objects into an array, and then adds these to the layout. It works for up to about 400 objects, but above that I get a “Stack overrun” error. Is this InDesign’s way of telling me it has run out of memory?

       

      Here is the first part of my code:

       

      var myFile = File.openDialog("Choose a data file");
      var listingString = "listing";
      var myArray = [];
      
      if((myFile != "") && (myFile != null)){
          
          var sourceFile = new File(myFile);
          sourceFile.open();
          var myString = sourceFile.read();
          sourceFile.close();
          
          var endIndex;
          var listingContents;
          var foundTags;
          var listing;
          var tagStart;
          var tagEnd;
          var tagContent;
          
          function checkString(startIndex){
              endIndex = myString.indexOf("</" + listingString + ">", startIndex);
              if(endIndex != -1){
                  listingContents = myString.slice(startIndex + 2 + listingString.length, endIndex);
                  foundTags = listingContents.match(/<[a-z ]+>/gi);
                  listing = {};
                  for(i = 0; i < foundTags.length; i++){
                      tagStart = listingContents.indexOf(foundTags[i]) + foundTags[i].length + 1;
                      tagEnd = listingContents.indexOf("</" + foundTags[i].substring(1)) - 1;
                      tagContent = listingContents.slice(tagStart, tagEnd);
                      listing[foundTags[i].substr(1, foundTags[i].length - 2)] = tagContent;
                  }
                  myArray.push(listing);
                  checkString(endIndex + 3 + listingString.length);
              }
          }
          
          checkString(myString.indexOf("<" + listingString + ">", 0));
          ...
      }
      

       

      Any suggestions on how I can fix it or optimise the code? I’m thinking of trying to split the string into multiple chunks and deal with one chunk at a time, but this seems like a clumsy workaround.

       

      You may have guessed from the code that the source file I’m working with is XML, though because I don’t have much experience with XML and it seemed like much more work than what I’ve done here I went with this approach. I also thought this may be more flexible. Might working with it as true XML make a difference with the memory issue (if that’s what it is)?

       

      I’m working in CS4 in Windows, but had the same problem in CS5 on a Mac that I tried.

       

      I’d appreciate any help.

        • 1. Re: Stack overrun
          Graham vdR Community Member

          Further to the question above, is there any way to manually clear memory? Say, for instance, that I populate myArray only until its length is 200, do the layout for those objects, and then clear it and continue with the string to fill it with the next 200 objects? I’ve tried to do this just using myArray = [] once I’ve laid out all its objects, but I still get the Stack overrun error.

          • 2. Re: Stack overrun
            [Jongware] CommunityMVP

            This is the reason:

             

            function checkString {

            if (..)

            checkString

            checkString

            }

             

            -- in each call, it calls itself at least once -- and possible twice.

             

            Try using the native XML object wrapper instead! See http://jongware.mit.edu/idcs6js/pc_XML.html for the available functionality.

             

            var sourceFile = new File(...);
                sourceFile.open();
                var myString = sourceFile.read();
                sourceFile.close();
            myXml = new XML (myString);
            // length is a *function* in XML!
            alert (myXml.length());
            

             

            This is sort of a chimeara, half Javascript, half XML, but it sounds like you can do all operations you want through this interface.

            • 3. Re: Stack overrun
              Graham vdR Community Member

              Many thanks for your feedback, Jongware. Unfortunately I’ll be out of town for a week from today, but I look forward to having a good look at it as soon as I return. I had hoped to resolve the issue before leaving, but it’ll have to wait!

               

              Thanks again.

               

              Graham

              • 4. Re: Stack overrun
                Graham vdR Community Member

                You’re quite right about the recursive function being the problem, Jongware (though I think you misread—it only calls itself once; the second call is the initialisation of the function). I thought that as long as it didn’t go into an infinite loop it would be alright. I wrote a simple test script and saw that I was wrong:

                 

                var myCounter = 0;

                function myFunction(){

                    myCounter++;

                    if(myCounter < 400){

                        myFunction();

                    }

                }

                myFunction();

                alert(myCounter);

                 

                Above 489 recursions it gives the stack overrun error. I changed it to a while loop and all seems to work fine. The XML object wrapper you suggest probably is the best solution, though, and will no doubt be useful down the line, so I’ll look into that.

                 

                Thanks again for your help.