[ http://issues.apache.org/jira/browse/XERCESC-1381?page=history ]
Christian Will updated XERCESC-1381: ------------------------------------ Attachment: GrammarResolver.cpp.patch my changes... > Memory Leak in GrammarResolver class > ------------------------------------ > > Key: XERCESC-1381 > URL: http://issues.apache.org/jira/browse/XERCESC-1381 > Project: Xerces-C++ > Type: Bug > Components: Validating Parser (Schema) (Xerces 1.5 or up only) > Versions: 2.6.0 > Environment: all > Reporter: Christian Will > Attachments: GrammarResolver.cpp.patch > > Hi, > the grammar resolver class produces memory leaks under some circumstances. If > we set the features fgXercesUseCachedGrammarInParse, > fgXercesCacheGrammarFromParse and lock the grammar pool all new created > grammars will never be deleted. > Here is my first example. I create a parser, cache the grammar, lock the > grammar pool and parse one instance document. I delete the parser object, > unlock and delete the grammar pool, and terminate the platform utils. After > all objects are deleted we can see that still 3 kbytes are allocated from the > grammar pool memory manager. > I could locate all allocations to [\internal\IGXMLScanner2.cpp(1146)]. > => "fDTDGrammar = new (fGrammarPoolMemoryManager) > DTDGrammar(fGrammarPoolMemoryManager);" > Sample Log 1 > ------------ > init... > parser1 set feature > SchemaFullChecking,UseCachedGrammarInParse,CacheGrammarFromParse > PlatformUtils: 172842 [ 172842]bytes, 2855 [ 3918, 1162]blocks (0) > Parser One : 26456 [ 26456]bytes, 101 [ 101, 0]blocks (0) > GrammarPool : 1214 [ 1214]bytes, 20 [ 20, 0]blocks (0) > cache grammar... (T:/testfiles/_FIXML/schema/FIXML-main-4-4.xsd) > PlatformUtils: 172842 [ 172842]bytes, 2855 [ 3918, 1162]blocks (0) > Parser One : 26456 [ 308510]bytes, 101 [ 2885, 4064]blocks (5) > GrammarPool : 4239962 [ 12829334]bytes, 62711 [117134, 70374]blocks (8) > lock grammarpool... > PlatformUtils: 172842 [ 172842]bytes, 2855 [ 3918, 1162]blocks (0) > Parser One : 26456 [ 308510]bytes, 101 [ 2885, 4064]blocks (0) > GrammarPool : 5501456 [ 12829334]bytes, 97049 [151874, 70776]blocks (0) > --------------------------------------------------------------------------- > parse with parser1... (T:/testfiles/_FIXML/order100.xml) > PlatformUtils: 172842 [ 172842]bytes, 2855 [ 3918, 1162]blocks (0) > Parser One : 50846 [ 308510]bytes, 517 [ 3395, 4370]blocks (40) > GrammarPool : 5504580 [ 12829334]bytes, 97064 [151889, 70776]blocks (4) > --------------------------------------------------------------------------- > delete parser1... > PlatformUtils: 172842 [ 172842]bytes, 2855 [ 3918, 1162]blocks (0) > GrammarPool : 5504580 [ 12829334]bytes, 97064 [151889, 70776]blocks (0) > unlock grammarPool... > PlatformUtils: 172842 [ 172842]bytes, 2855 [ 3918, 1162]blocks (0) > GrammarPool : 4243086 [ 12829334]bytes, 62726 [151889,105114]blocks (0) > delete grammarPool... > PlatformUtils: 172842 [ 172842]bytes, 2855 [ 3918, 1162]blocks (0) > GrammarPool : 3020 [ 12829334]bytes, 12 [151889,176419]blocks (0) > terminate PlatformUtils... > GrammarPool : 3020 [ 12829334]bytes, 12 [151889,176419]blocks (0) > done. > ==-still-allocated-memory-================================================= > pointer: 3df83c0 size: 44bytes sequence: 151875 > T:\xerces_cvs\src\xercesc\util\XMemory.cpp(66) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner2.cpp(1146) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner.cpp(188) > T:\xerces_cvs\src\xercesc\internal\XMLScanner.cpp(434) > pointer: 3df86d0 size: 32bytes sequence: 151876 > T:\xerces_cvs\src\xercesc\util\XMemory.cpp(66) > T:\xerces_cvs\src\xercesc\validators\DTD\DTDGrammar.cpp(169) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner2.cpp(1146) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner.cpp(188) > pointer: 3df87d8 size: 436bytes sequence: 151877 > ..\..\..\..\..\src\xercesc/util/NameIdPool.c(122) > T:\xerces_cvs\src\xercesc\validators\DTD\DTDGrammar.cpp(169) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner2.cpp(1146) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner.cpp(188) > pointer: 3df8a70 size: 512bytes sequence: 151878 > ..\..\..\..\..\src\xercesc/util/NameIdPool.c(136) > T:\xerces_cvs\src\xercesc\validators\DTD\DTDGrammar.cpp(169) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner2.cpp(1146) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner.cpp(188) > pointer: 3df8d58 size: 32bytes sequence: 151879 > T:\xerces_cvs\src\xercesc\util\XMemory.cpp(66) > T:\xerces_cvs\src\xercesc\validators\DTD\DTDGrammar.cpp(173) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner2.cpp(1146) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner.cpp(188) > pointer: 3df8e60 size: 436bytes sequence: 151880 > ..\..\..\..\..\src\xercesc/util/NameIdPool.c(122) > T:\xerces_cvs\src\xercesc\validators\DTD\DTDGrammar.cpp(173) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner2.cpp(1146) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner.cpp(188) > pointer: 3df90f8 size: 512bytes sequence: 151881 > ..\..\..\..\..\src\xercesc/util/NameIdPool.c(136) > T:\xerces_cvs\src\xercesc\validators\DTD\DTDGrammar.cpp(173) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner2.cpp(1146) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner.cpp(188) > pointer: 3df93e0 size: 32bytes sequence: 151882 > T:\xerces_cvs\src\xercesc\util\XMemory.cpp(66) > T:\xerces_cvs\src\xercesc\validators\DTD\DTDGrammar.cpp(174) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner2.cpp(1146) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner.cpp(188) > pointer: 3df94e8 size: 436bytes sequence: 151883 > ..\..\..\..\..\src\xercesc/util/NameIdPool.c(122) > T:\xerces_cvs\src\xercesc\validators\DTD\DTDGrammar.cpp(174) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner2.cpp(1146) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner.cpp(188) > pointer: 3df9780 size: 512bytes sequence: 151884 > ..\..\..\..\..\src\xercesc/util/NameIdPool.c(136) > T:\xerces_cvs\src\xercesc\validators\DTD\DTDGrammar.cpp(174) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner2.cpp(1146) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner.cpp(188) > pointer: 3df9a68 size: 24bytes sequence: 151885 > T:\xerces_cvs\src\xercesc\util\XMemory.cpp(66) > T:\xerces_cvs\src\xercesc\validators\DTD\DTDGrammar.cpp(177) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner2.cpp(1146) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner.cpp(188) > pointer: 3df9b60 size: 12bytes sequence: 151886 > ..\..\..\..\..\src\xercesc/util/XMLString.hpp(1667) > T:\xerces_cvs\src\xercesc\validators\DTD\XMLDTDDescriptionImpl.cpp(59) > T:\xerces_cvs\src\xercesc\validators\DTD\DTDGrammar.cpp(177) > T:\xerces_cvs\src\xercesc\internal\IGXMLScanner2.cpp(1146) > ==-still-allocated-memory-================================================= > My second example shows the impact a little bit better. I lock the grammar > pool without loading the grammar. I parse the instance document 3 times. And > after I delete all objects and terminate the platform utils I can see that > the associated grammar is still 3 times (11.5MB) in memory. > Sample Log 2 > ------------ > init... > parser1 set feature > SchemaFullChecking,UseCachedGrammarInParse,CacheGrammarFromParse > PlatformUtils: 172842 [ 172842]bytes, 2855 [ 3918, 1162]blocks (0) > Parser One : 26456 [ 26456]bytes, 101 [ 101, 0]blocks (0) > GrammarPool : 1214 [ 1214]bytes, 20 [ 20, 0]blocks (0) > lock grammarpool... > PlatformUtils: 172842 [ 172842]bytes, 2855 [ 3918, 1162]blocks (0) > Parser One : 26456 [ 26456]bytes, 101 [ 101, 0]blocks (0) > GrammarPool : 23934 [ 24098]bytes, 597 [ 629, 32]blocks (0) > --------------------------------------------------------------------------- > parse with parser1... (T:/testfiles/_FIXML/order100.xml) > PlatformUtils: 172842 [ 172842]bytes, 2855 [ 3918, 1162]blocks (0) > Parser One : 50862 [ 486594]bytes, 517 [ 3392, 4374]blocks (40) > GrammarPool : 4265794 [ 12855178]bytes, 63302 [117757, 70406]blocks (5) > parse with parser1... (T:/testfiles/_FIXML/order100.xml) > PlatformUtils: 172842 [ 172842]bytes, 2855 [ 3918, 1162]blocks (0) > Parser One : 52466 [ 497174]bytes, 586 [ 6317, 8535]blocks (65) > GrammarPool : 8120878 [ 16710262]bytes,115564 [224426,140764]blocks (0) > parse with parser1... (T:/testfiles/_FIXML/order100.xml) > PlatformUtils: 172842 [ 172842]bytes, 2855 [ 3918, 1162]blocks (0) > Parser One : 54586 [ 498778]bytes, 655 [ 9241, 12695]blocks (144) > GrammarPool : 11975962 [ 20565346]bytes,167826 [331095,211122]blocks (0) > --------------------------------------------------------------------------- > delete parser1... > PlatformUtils: 172842 [ 172842]bytes, 2855 [ 3918, 1162]blocks (0) > GrammarPool : 11975962 [ 20565346]bytes,167826 [331095,211122]blocks (0) > unlock grammarPool... > PlatformUtils: 172842 [ 172842]bytes, 2855 [ 3918, 1162]blocks (0) > GrammarPool : 11953242 [ 20565346]bytes,167249 [331095,211699]blocks (0) > delete grammarPool... > PlatformUtils: 172842 [ 172842]bytes, 2855 [ 3918, 1162]blocks (0) > GrammarPool : 11565252 [ 20565346]bytes,156786 [331095,222162]blocks (0) > terminate PlatformUtils... > GrammarPool : 11565252 [ 20565346]bytes,156786 [331095,222162]blocks (0) > Let me try to explain why this is happening. In GrammarResolver::putGrammar() > can we see that we put our grammar in the table 'fGrammarBucket' if we don't > want to cache our grammar or the grammar pool doesn't want cache our grammar > (because it is locked). > void GrammarResolver::putGrammar(Grammar* const grammarToAdopt) > { > ... > if (!fCacheGrammar || !fGrammarPool->cacheGrammar(grammarToAdopt)) > { > // either we aren't caching or the grammar pool doesn't want it > // so we need to look after it > fGrammarBucket->put( (void*) > grammarToAdopt->getGrammarDescription()->getGrammarKey(), grammarToAdopt ); > if (grammarToAdopt->getGrammarType() == Grammar::SchemaGrammarType) > { > fGrammarsToAddToXSModel->addElement((SchemaGrammar*) > grammarToAdopt); > } > } > } > So far so good. We have all grammars that we don't want to cache or/and can't > be cached in this table. So normaly if it deletes the table fGrammarBucket > all grammars will be deleted. But if the feature > fgXercesCacheGrammarFromParse is set it changes the behavior of the table to > not adopte the elements. What we can see in > GrammarResolver::cacheGrammarFromParse(). > void GrammarResolver::cacheGrammarFromParse(const bool aValue) > { > reset(); > fCacheGrammar = aValue; > fGrammarBucket->setAdoptElements(!fCacheGrammar); > } > I think that is wrong to change the property of our table to not adopt the > elements. Whenever we remove an grammar from our list, for example to cache > to grammar, we call fGrammarBucket->orphanKey(grammarKey), and that means > already that we remove the grammar wihtout deleting it. > I removed this line "fGrammarBucket->setAdoptElements(!fCacheGrammar);" made > some tests and everything looks good. > But I'm not sure if there are no side effects. And that is the reason why I > would like to get a second opinion from somebody. I can also send parts of my > code If you have problems to reproduce the bug. > Regards, > Christian Will -- This message is automatically generated by JIRA. - If you think it was sent incorrectly contact one of the administrators: http://issues.apache.org/jira/secure/Administrators.jspa - If you want more information on JIRA, or have a bug to report see: http://www.atlassian.com/software/jira --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]