LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

xml memory leak (?)

Ho out there,

Maybe i´m totally wrong, but i have real trouble in some xml parsing code i use in a current project leaking memory.

I use cvi 8.5 on a XP machine with 2 GB Ram.

The code i extracted is part of a bigger application, which i condensed down to the problem i see: it is called several times and after leaving the subroutine, lots of memory is missing (in this test case about 40 MB per round).
The xml file that is parsed is valid and not too small (but i can´t post it due to privacy issues with our customers).

void test (void)
{
    int iLoop, iStatus;
    char cDir[300];
    char cLanguage[255];
    char cErrorString[255];
    int  inum_elements,inum_sub_elements;   
    int  iMaxIndex; 
    int  iElementIndex;
    int  iSubElements;
    int  iElementLength, iValueLength;
    int  iLength;
    int  iSelIndex;
    int  iError;
    int  iIndex=0;
 
    char str[255];  
    char str1[255];
    char str2[9999];
    char str3[255]; 
   
    CVIXMLDocument document2;  
    CVIXMLElement  xml_curr_lang,xml_element,xml_element_dummy,xml_element_dummy2;
    CVIXMLAttribute xml_attr;
    ListType       list=0,sublist=0;

    for(iLoop=0; iLoop<100; iLoop++)
    {
        // set pointer to requ. file
        sprintf(Para.cParaID,"A 1"),
        ui64ID=900360001;
        GetProjectDir(cDir);
        sprintf(proj_dir,"%s%s%I64d%s",cDir,"\\Data\\",ui64ID,".xml");
        iStatus=CVIXMLLoadDocument(proj_dir,&document2);

        sprintf(cLanguage,"de");            //sel language

        xml_curr_lang=xml_element=xml_element_dummy=0;
        xml_attr=0;

        if(iStatus!=0)
        {
            CVIXMLGetErrorString (iStatus, cErrorString, 255);
        }       

        if(iStatus==0)
        {
            ErrorHandler(CVIXMLGetRootElement(document2,&xml_element),"XML Error");
            ErrorHandler(CVIXMLGetNumChildElements(xml_element,&inum_elements),"XML Error"); //  => Root Verzeichnis adressieren

            iStatus=CVIXMLFindElements(xml_element,"sprache",&list);                             // Sprachebene adressieren
            inum_elements= ListNumItems (list);

            // ------------------------------------------ nach Sprache suchen

            iStatus=0;
            iMaxIndex=0;

            for(iElementIndex=0; iElementIndex<inum_elements; iElementIndex++)                   // Suchen, bis die gewünschte Sprache gefunden wird
            {
                ListGetItem(list,&xml_element_dummy,iElementIndex+1);

                CVIXMLGetElementTagLength(xml_element_dummy, &iElementLength);
                if(iElementLength>=255)
                {
                    exit(0);                     // error handler
                }                  

                CVIXMLGetElementTag(xml_element_dummy,str2);
                ErrorHandler(CVIXMLGetAttributeByName(xml_element_dummy,"id",&xml_attr),"Tag >ID< unter >sprache< nicht gefunden"); //  => Root Verzeichnis adressieren    
                ErrorHandler(CVIXMLGetAttributeValue(xml_attr,str1),"ID liefert keinen Wert zurück");

                if(CompareStrings(cLanguage,0,str1,0,0)==0)
                {
                    iStatus=1; 
                    break;
                }

                CVIXMLDiscardAttribute(xml_attr);
            }

            if(iStatus==0)
            {
                exit(0); // error handler
            }
//***
        }
        xml_curr_lang=xml_element_dummy;       
    }   
 
    CVIXMLDiscardElement(xml_curr_lang);
    CVIXMLDiscardElement(xml_element);
    CVIXMLDiscardElement(xml_element_dummy);

    CVIXMLDiscardAttribute(xml_attr);  
    ListDispose(list);
    ListDispose(sublist);       
    CVIXMLDiscardDocument(document2); 

}


Maybe there is a simple solution i cannot come up with: again, the memory leak persists even after leaving that subroutine. It only disappears after leaving the main programme..

Thanks in advance.

DoS

edit:

void ErrorHandler(int icode, char ucData[])
{
    if (icode>=0)
    {
        return;
    }
    else
    {
        MessagePopup("Fehler",ucData);
        exit (0);
    }
}


Message Edited by dos on 08-08-2008 07:28 AM
0 Kudos
Message 1 of 12
(4,830 Views)
Hi dos,

It's hard to tell looking at the code without running it. I tried running it myself, but I would need the actual xml file to be present. What I would recommend would be for you to download the beta version that was just announced for the latest version of CVI (see the announcement post at the top of the main forum page). In it, there are some tools that might help you find out if some of the XML handles are not being disposed properly.

Luis
0 Kudos
Message 2 of 12
(4,814 Views)
Thanks very much on your reply. I could send you the xml file via private mail (quite too big to attach) on monday when i´m back in office.

Using a beta version has some kind of complications on a productive system. I would be willing to try it but i would have to backup and setup a virtual machine in the first place. And all that copyprotection stuff doesn´t make that sooo easy.

It took me a day to condense down to the above code which caused the problem and i can´t spend a week on that (after all my company has to earn money - at least that´s what my boss says).

thanks very much

DoS
0 Kudos
Message 3 of 12
(4,807 Views)
Yeah, I understand. In that case, would you like to submit a test program to our FTP site, and then let me know here after you submit it? I'd be happy to take a look at it and see if I can find the problem.

Luis
0 Kudos
Message 4 of 12
(4,802 Views)
Good morning again (at least in my time zone),

thanks very much for the offer: i uploaded the file 900360001.xml to the ftp server. That is exactly the file referenced in my sample code. Every run increases my memory usage by about 40 MB (!).
Would be so glad, if you could point me to a mistake i made...

all the best

Dominik

edit: please remove the file after processing.


Message Edited by dos on 08-11-2008 01:23 AM
0 Kudos
Message 5 of 12
(4,782 Views)
Hello Dominik,

The primary reason for the memory leak is that you are allocating xml handles in each iteration of the loop, but you're only discarding them once, after the loop has completed. You can fix the memory leaks by adding the following code:

At the end of, but inside, the innermost loop (iElementIndex<inum_elements):

        CVIXMLDiscardAttribute(xml_attr); 

At the end of, but inside, the outer loop (iLoop<100):

        for (iElementIndex = 0; iElementIndex < inum_elements; iElementIndex++)
        {
                ListRemoveItem (list, &xml_element_to_dispose, FRONT_OF_LIST);
                CVIXMLDiscardElement (xml_element_to_dispose);
        }
        ListDispose (list);
        CVIXMLDiscardElement (xml_element);
        CVIXMLDiscardDocument (document2);

Note that, not only do you have to dispose the list that you get back from the CVIXMLFindElements function, but you also have to dispose each element in that list, hence the additional loop.

Let me know if you have any other questions!

Luis
0 Kudos
Message 6 of 12
(4,761 Views)

l First of all thanks for the immediate reply. I´m still fighting on that problem... A few things i stumbled uppon the last two days:

 

*** CVIXMLCopyElement: there is  sth wrong with the help text: the number of parameters do not match the parameters explained in the text and (what is worse) in no way matches what the compiler expected (even one more argument).

 

*** Beta CVI: as you recommended above, i applied for the beta software, but the standard form says, that this is updated on a yearly base (which could mean, that it may take 364 day to wait (worst case) until a reply arrives - which is not a good option right now)

 

*** Problem with that code line:

 

     iStatus=CVIXMLFindElements(xml_element,"sprache",&list1);

 

I totally missed to allocate that list, but couldn´t find a example to explain to me, how i reserve a list of xml elements.

 

*** now i get problems with "dynamic momory corrput" at changing positions - looks like it changes according to the memory leak i just fixed. 

 

*** Is there a way to find out, which elements are not cleanly removed (i found some hints which only work in lower version of CVI)...

 

 

Thanks for your advice...

 

Dominik

0 Kudos
Message 7 of 12
(4,727 Views)

I did some more tries: i took my "real" program and commented out almost everything. The subroutine i included is run 100-200 times and the memory is allocated massively (about 100 MB). It runs the file i sent to your ftp server some days ago.

 

I´m really stuck  in searching for the problem. I know those XML Elements at the end should be freed, but they tend to cause me errors when uncommented.

 

-----------------------------------------

0 Kudos
Message 8 of 12
(4,726 Views)

Hi Dominik,

 

I'm attaching your code after I made a few corrections. I've explained each modification with a comment that starts with "MOD:". Let me know if any of them is unclear. Essentially, the problem you were having is that you were freeing some of the elements more than once, and others (mainly the lists, but also an element or two) were not being freed at all. The comments should explain it.

 

I checked the help for CVIXMLCopyElement, both in the function panel, and in the external help, and I didn't find a problem with the number of parameters. The function expects five parameters:

 

CVIXMLCopyElement (CVIXMLElement srcElem, int copyChildElements,

                   CVIXMLElement destParent, int index, CVIXMLElement *destElem);

 

What do you see in the help?

 

As far as the beta is concerned, yes it does follow (roughly) an annual cycle, but currently there is an active beta program, so at this time of the year you should receive a reply within a day or two (note the beta announcement that was posted here in the forum just last week). To answer your last question, if you use the beta, you can get a report of which elements were not cleanly removed.

 

An example for how to deallocate the list that you get from CVIXMLFindElements can be found in the function help itself. Look at the help for the last parameter.

 

Luis

Message Edited by LuisG on 08-13-2008 02:33 PM
0 Kudos
Message 9 of 12
(4,712 Views)

Hi Luis,

 

first of THANKS VERY MUCH. I got it running - finally.

 

****

One of your comments rang a bell: I didn´t realize that i should not have to dispose an xml element which was  part of a list already being removed. I removed that element explicitely which caused the hell of a number of dynamic memory errors which lead me to not free enough elements finally.

 

****

CVIXMLCopyElement
CVIXMLStatus CVIXMLCopyElement (CVIXMLElement element, int copyChildren, CVIXMLElement parentElement);


Thats what the internal help of my version (8.5) returns - and i think we agree - thats kind of wrong).

 

****

kind of follow up question: i cannot find any example for writing xml files. 

I feel quiter stupid, but i don´t understand how to add a new element with cvixmlnewelelment, as it refers to a parent element i do not have (i´m using an empty list).

 

Thanks again for your great help!

 

0 Kudos
Message 10 of 12
(4,694 Views)