Skip to content

window crt report memory leak #63

Open
@yetuweiba

Description

@yetuweiba

Hi,buddy

I have run the dom_parser test code in debugmode, and add code of crt memory check. in the output, vs tell me have some memory leak,
the output are:

Detected memory leaks!
Dumping objects ->
{188} normal block at 0x00E4EF68, 12 bytes long.
 Data: <    0L z`L z> 20 EF E4 00 30 4C E9 7A 60 4C E9 7A 
{187} normal block at 0x00E4EF20, 12 bytes long.
 Data: <ISO-8859-16 > 49 53 4F 2D 38 38 35 39 2D 31 36 00 
{186} normal block at 0x00E4EED8, 12 bytes long.
 Data: <     K z L z> 90 EE E4 00 D0 4B E9 7A 00 4C E9 7A 
{185} normal block at 0x00E4EE90, 12 bytes long.
 Data: <ISO-8859-15 > 49 53 4F 2D 38 38 35 39 2D 31 35 00 
{184} normal block at 0x00E4EE48, 12 bytes long.
 Data: <    pK z K z> 00 EE E4 00 70 4B E9 7A A0 4B E9 7A 
{183} normal block at 0x00E4EE00, 12 bytes long.
 Data: <ISO-8859-14 > 49 53 4F 2D 38 38 35 39 2D 31 34 00 
{182} normal block at 0x00E4EDB8, 12 bytes long.
 Data: <p    K z@K z> 70 ED E4 00 10 4B E9 7A 40 4B E9 7A 
{181} normal block at 0x00E4ED70, 12 bytes long.
 Data: <ISO-8859-13 > 49 53 4F 2D 38 38 35 39 2D 31 33 00 
{180} normal block at 0x00E4ED28, 12 bytes long.
 Data: <     J z J z> E0 EC E4 00 B0 4A E9 7A E0 4A E9 7A 
{179} normal block at 0x00E4ECE0, 12 bytes long.
 Data: <ISO-8859-11 > 49 53 4F 2D 38 38 35 39 2D 31 31 00 
{178} normal block at 0x00E4EC98, 12 bytes long.
 Data: <P   PJ z J z> 50 EC E4 00 50 4A E9 7A 80 4A E9 7A 
{177} normal block at 0x00E4EC50, 12 bytes long.
 Data: <ISO-8859-10 > 49 53 4F 2D 38 38 35 39 2D 31 30 00 
{176} normal block at 0x00E4EC08, 12 bytes long.
 Data: <     I z J z> C0 EB E4 00 F0 49 E9 7A 20 4A E9 7A 
{175} normal block at 0x00E4EBC0, 11 bytes long.
 Data: <ISO-8859-9 > 49 53 4F 2D 38 38 35 39 2D 39 00 
{174} normal block at 0x00E4EB78, 12 bytes long.
 Data: <0    I z I z> 30 EB E4 00 90 49 E9 7A C0 49 E9 7A 
{173} normal block at 0x00E4EB30, 11 bytes long.
 Data: <ISO-8859-8 > 49 53 4F 2D 38 38 35 39 2D 38 00 
{172} normal block at 0x00E4EAE8, 12 bytes long.
 Data: <    0I z`I z> A0 EA E4 00 30 49 E9 7A 60 49 E9 7A 
{171} normal block at 0x00E4EAA0, 11 bytes long.
 Data: <ISO-8859-7 > 49 53 4F 2D 38 38 35 39 2D 37 00 
{170} normal block at 0x00E4EA58, 12 bytes long.
 Data: <     H z I z> 10 EA E4 00 D0 48 E9 7A 00 49 E9 7A 
{169} normal block at 0x00E4EA10, 11 bytes long.
 Data: <ISO-8859-6 > 49 53 4F 2D 38 38 35 39 2D 36 00 
{168} normal block at 0x00E4E9C8, 12 bytes long.
 Data: <    pH z H z> 80 E9 E4 00 70 48 E9 7A A0 48 E9 7A 
{167} normal block at 0x00E4E980, 11 bytes long.
 Data: <ISO-8859-5 > 49 53 4F 2D 38 38 35 39 2D 35 00 
{166} normal block at 0x00E4E938, 12 bytes long.
 Data: <     H z@H z> F0 E8 E4 00 10 48 E9 7A 40 48 E9 7A 
{165} normal block at 0x00E4E8F0, 11 bytes long.
 Data: <ISO-8859-4 > 49 53 4F 2D 38 38 35 39 2D 34 00 
{164} normal block at 0x00E4E8A8, 12 bytes long.
 Data: <`    G z G z> 60 E8 E4 00 B0 47 E9 7A E0 47 E9 7A 
{163} normal block at 0x00E4E860, 11 bytes long.
 Data: <ISO-8859-3 > 49 53 4F 2D 38 38 35 39 2D 33 00 
{162} normal block at 0x00E4E818, 12 bytes long.
 Data: <    PG z G z> D0 E7 E4 00 50 47 E9 7A 80 47 E9 7A 
{161} normal block at 0x00E4E7D0, 11 bytes long.
 Data: <ISO-8859-2 > 49 53 4F 2D 38 38 35 39 2D 32 00 
{160} normal block at 0x00E4E788, 12 bytes long.
 Data: <@        ' z> 40 E7 E4 00 00 00 00 00 A7 27 E7 7A 
{159} normal block at 0x00E4E740, 5 bytes long.
 Data: <HTML > 48 54 4D 4C 00 
{158} normal block at 0x00E4E6F8, 12 bytes long.
 Data: <     0 zP1 z> B0 E6 E4 00 90 30 E9 7A 50 31 E9 7A 
{157} normal block at 0x00E4E6B0, 9 bytes long.
 Data: <US-ASCII > 55 53 2D 41 53 43 49 49 00 
{156} normal block at 0x00E4E668, 12 bytes long.
 Data: <     0 zP1 z> 20 E6 E4 00 90 30 E9 7A 50 31 E9 7A 
{155} normal block at 0x00E4E620, 6 bytes long.
 Data: <ASCII > 41 53 43 49 49 00 
{154} normal block at 0x00E4E5D8, 12 bytes long.
 Data: <       z   z> 90 E5 E4 00 19 1F E7 7A CD 1A E7 7A 
{153} normal block at 0x00E4E590, 11 bytes long.
 Data: <ISO-8859-1 > 49 53 4F 2D 38 38 35 39 2D 31 00 
{152} normal block at 0x00E4E548, 12 bytes long.
 Data: <     4 z0: z> 00 E5 E4 00 20 34 E9 7A 30 3A E9 7A 
{151} normal block at 0x00E4E500, 7 bytes long.
 Data: <UTF-16 > 55 54 46 2D 31 36 00 
{150} normal block at 0x00E4E4B8, 12 bytes long.
 Data: <p    : z = z> 70 E4 E4 00 B0 3A E9 7A 90 3D E9 7A 
{149} normal block at 0x00E4E470, 9 bytes long.
 Data: <UTF-16BE > 55 54 46 2D 31 36 42 45 00 
{148} normal block at 0x00E4E428, 12 bytes long.
 Data: <     4 z 6 z> E0 E3 E4 00 20 34 E9 7A F0 36 E9 7A 
{147} normal block at 0x00E4E3E0, 9 bytes long.
 Data: <UTF-16LE > 55 54 46 2D 31 36 4C 45 00 
{146} normal block at 0x00E4E398, 12 bytes long.
 Data: <P    3 z 3 z> 50 E3 E4 00 80 33 E9 7A 80 33 E9 7A 
{145} normal block at 0x00E4E350, 6 bytes long.
 Data: <UTF-8 > 55 54 46 2D 38 00 
{144} normal block at 0x00E4E248, 200 bytes long.
 Data: <    (       H   > 98 E3 E4 00 28 E4 E4 00 B8 E4 E4 00 48 E5 E4 00 
{143} normal block at 0x00E4D3C0, 4 bytes long.
 Data: <    > E8 00 00 00 
{142} normal block at 0x00E4D368, 28 bytes long.
 Data: <                > FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00 00 
{141} normal block at 0x00E4D328, 4 bytes long.
 Data: <    > E4 00 00 00 
{140} normal block at 0x00E4D2D0, 24 bytes long.
 Data: <                > FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00 00 

libxml2 version is 2.11.4, libxml++ is 5.0.3, they are all build in x86 debug. and my os is windows 10 x64.

here is my test code:

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>


#include <libxml++/libxml++.h>
#include <iostream>
#include <cstdlib>

void print_node(const xmlpp::Node* node, unsigned int indentation = 0)
{
    const std::string indent(indentation, ' ');
    std::cout << std::endl; //Separate nodes by an empty line.

    const auto nodeContent = dynamic_cast<const xmlpp::ContentNode*>(node);
    const auto nodeText = dynamic_cast<const xmlpp::TextNode*>(node);
    const auto nodeComment = dynamic_cast<const xmlpp::CommentNode*>(node);

    if (nodeText && nodeText->is_white_space()) //Let's ignore the indenting - you don't always want to do this.
        return;

    const auto nodename = node->get_name();

    std::cout << indent << "Node start-----------------------" << std::endl;

    if (!nodeText && !nodeComment && !nodename.empty()) //Let's not say "name: text".
    {
        const auto namespace_prefix = node->get_namespace_prefix();

        std::cout << indent << "Node name = ";
        if (!namespace_prefix.empty())
            std::cout << namespace_prefix << ":";
        std::cout << nodename << std::endl;
    }
    else if (nodeText) //Let's say when it's text. - e.g. let's say what that white space is.
    {
        std::cout << indent << "Text Node" << std::endl;
    }

    //Treat the various node types differently:
    if (nodeText)
    {
        std::cout << indent << "text = \"" << nodeText->get_content() << "\"" << std::endl;
    }
    else if (nodeComment)
    {
        std::cout << indent << "comment = " << nodeComment->get_content() << std::endl;
    }
    else if (nodeContent)
    {
        std::cout << indent << "content = " << nodeContent->get_content() << std::endl;
    }
    else if (auto nodeElement = dynamic_cast<const xmlpp::Element*>(node))
    {
        //A normal Element node:

        //line() works only for ElementNodes.
        int line = node->get_line();
        printf("     line = %d", line);

        //Print attributes:
        for (const auto& attribute : nodeElement->get_attributes())
        {
            const auto namespace_prefix = attribute->get_namespace_prefix();

            std::cout << indent << "  Attribute ";
            if (!namespace_prefix.empty())
                std::cout << namespace_prefix << ":";
            std::cout << attribute->get_name() << " = "
                << attribute->get_value() << std::endl;
        }

        const auto attribute = nodeElement->get_attribute("title");
        if (attribute)
        {
            std::cout << indent;
            if (dynamic_cast<const xmlpp::AttributeNode*>(attribute))
                std::cout << "AttributeNode ";
            else if (dynamic_cast<const xmlpp::AttributeDeclaration*>(attribute))
                std::cout << "AttributeDeclaration ";
            std::cout << "title = " << attribute->get_value() << std::endl;
        }
    }

    if (!nodeContent)
    {
        //Recurse through child nodes:
        for (const auto& child : node->get_children())
        {
            print_node(child, indentation + 2); //recursive
        }
    }
}

int main(int argc, char* argv[])
{
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

    _CrtSetBreakAlloc(199);
    bool validate = false;
    bool set_throw_messages = false;
    bool throw_messages = false;
    bool substitute_entities = true;
    bool include_default_attributes = false;

    int argi = 1;
    while (argc > argi && *argv[argi] == '-') // option
    {
        switch (*(argv[argi] + 1))
        {
        case 'v':
            validate = true;
            break;
        case 't':
            set_throw_messages = true;
            throw_messages = true;
            break;
        case 'e':
            set_throw_messages = true;
            throw_messages = false;
            break;
        case 'E':
            substitute_entities = false;
            break;
        case 'a':
            include_default_attributes = true;
            break;
        default:
            std::cout << "Usage: " << argv[0] << " [-v] [-t] [-e] [filename]" << std::endl
                << "       -v  Validate" << std::endl
                << "       -t  Throw messages in an exception" << std::endl
                << "       -e  Write messages to stderr" << std::endl
                << "       -E  Do not substitute entities" << std::endl
                << "       -a  Include default attributes in the node tree" << std::endl;
            return EXIT_FAILURE;
        }
        argi++;
    }
    std::string filepath;
    if (argc > argi)
        filepath = argv[argi]; //Allow the user to specify a different XML file to parse.
    else
        filepath = "D:\\test\\Test\\libxmlpp_test\\Config.xml";

    try
    {
        xmlpp::DomParser parser;
        if (validate)
            parser.set_validate();
        if (set_throw_messages)
            parser.set_throw_messages(throw_messages);

        parser.set_substitute_entities(substitute_entities);
        parser.set_include_default_attributes(include_default_attributes);
        parser.parse_file(filepath);
        if (parser)
        {
            //Walk the tree:
            const auto pNode = parser.get_document()->get_root_node(); //deleted by DomParser.
            print_node(pNode);
        }
    }
    catch (const std::exception& ex)
    {
        std::cerr << "Exception caught: " << ex.what() << std::endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

the function _CrtSetBreakAlloc document url is https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/crtsetbreakalloc?view=msvc-170 .
I have use windbg to load the exe,and input g twice(g is a command of continue),in the second breakpoint,we can see the stack information:

[0x0]   ucrtbased!heap_alloc_dbg_internal+0x6b   0x96f878   0x7babc616   
[0x1]   ucrtbased!heap_alloc_dbg+0x36   0x96f8cc   0x7babee3a   
[0x2]   ucrtbased!_malloc_dbg+0x1a   0x96f8f0   0x7babf7a4   
[0x3]   ucrtbased!malloc+0x14   0x96f908   0x7ae409ed   
[0x4]   xml___vc142_d_5_0!operator new+0xd   0x96f920   0x7ae39825   
[0x5]   xml___vc142_d_5_0!xmlpp::DomParser::DomParser+0x65   0x96f930   0xb097f8   
[0x6]   libxmlpp_test!main+0x2d8   0x96f980   0xb13d73   
[0x7]   libxmlpp_test!invoke_main+0x33   0x96fb3c   0xb13bc7   
[0x8]   libxmlpp_test!__scrt_common_main_seh+0x157   0x96fb5c   0xb13a5d   
[0x9]   libxmlpp_test!__scrt_common_main+0xd   0x96fbb8   0xb13df8   
[0xa]   libxmlpp_test!mainCRTStartup+0x8   0x96fbc0   0x76bffcc9   
[0xb]   KERNEL32!BaseThreadInitThunk+0x19   0x96fbc8   0x770d7c6e   
[0xc]   ntdll!__RtlUserThreadStart+0x2f   0x96fbd8   0x770d7c3e   
[0xd]   ntdll!_RtlUserThreadStart+0x1b   0x96fc34   0x0   

in the 0x5, I found request memory code is:

namespace xmlpp
{
DomParser::DomParser()
: doc_(nullptr)
{
  //Start with an empty document:
  doc_ = new Document();
}

So I can not understand what happend...
Thanks for read it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions