Possible memory leak on QDnsLookup?



  • Hi there, i'v been developing a small DNS server for caching some request in local (dnsmasq / BIND like). For that, I use a QMap for caching request and a QDnsLookup for domains I can't resolve locally.

    Everything works fine, until QDnsLookup gets in. I'v been profiling the application for memory leaks and i'v discovered everytime I call the method 'lookup' from a QDnsLookup instance, a memory leak of ~9kb appears. The slot where I connect the lookup instance is totally empty, and I free the instance correctly.

    If I don't call the 'lookup' method, no memory leaks appears, so I was thinking about QDnsLookup class having a memory leak.

    This is the class that I use as the DNS resolver

    #include "dnsresolver.h"
    
    quint32 DNSResolver::resolveDomain(QString domain)
    {
        if (cacheResolved){
            return cache->value(domain).toIPv4Address();
        }else{
            lookup->lookup();
            return 0;
        }
    }
    
    void DNSResolver::handleExternalResolve()
    {
        if (!lookup->hostAddressRecords().isEmpty()){
            auto record = lookup->hostAddressRecords().first();
            auto host = record.value();
    
            dnspack->addArecord(host.toIPv4Address());
            cache->insert(dnspack->domain, host);
        }
    
        delete lookup;
        emit sendResponse(*dnspack->datagram, senderHost.toIPv4Address(), senderPort);
    }
    
    DNSResolver::DNSResolver(t_resolve t, QObject *parent)
        : QThread(parent)
    {
        this->socket = t.socket;
        this->datagram = t.datagram;
        this->senderHost = t.senderHost;
        this->cache = t.cache;
        this->senderPort = t.senderPort;
    
        // Alloc a DNS packet for parsing
        dnspack = new DNS;
        dnspack->parse(&datagram);
        dnspack->makeAnswer();
    
        // Check if we can resolve by cache
        cacheResolved = cache->contains(dnspack->domain);
    
        if (!cacheResolved){
            // Alloc a external lookup object
            this->lookup = new QDnsLookup(QDnsLookup::A, dnspack->domain, QHostAddress(FORWARDING_DNS_SERVER));
            connect(lookup, SIGNAL(finished()), this, SLOT(handleExternalResolve()));
        }
    
    }
    
    DNSResolver::~DNSResolver()
    {
        delete dnspack;
    }
    
    void DNSResolver::run()
    {
        auto ip = resolveDomain(dnspack->domain);
        if (ip != 0){
            dnspack->addArecord(ip);
            emit sendResponse(*dnspack->datagram, senderHost.toIPv4Address(), senderPort);
        }
    }
    

    Thanks!!!!


  • Lifetime Qt Champion

    Hi,

    What version of Qt are you using ? On what platform ?

    Can you reproduce that with a smaller example ?



  • Qt 5.8, macOS 10.12.4.
    That's only a simple use case, but as I said, the problem can be reproduced just instancing a QDnsLookup instance and calling the lookup method. This is an smaller example.

    #include "dnsresolver.h"
    
    DnsResolver::DnsResolver(QObject *parent) : QObject(parent)
    {
        lookup = new QDnsLookup(QDnsLookup::A, "qt.io",QHostAddress("8.8.8.8"));
        connect(lookup, SIGNAL(finished()), this, SLOT(handleLookup()));
        lookup->lookup();
    }
    
    void DnsResolver::handleLookup()
    {
        // I use sleep for letting the profiler inspect the memory trace with enough time
        QThread::sleep(10);
    
        // I won't use lookup anymore
        delete lookup;
    
        // Let's close the app
        QCoreApplication::quit();
    }
    
    

    This code gives me a memory leak of 944 bytes on 'libresolv'. I don't know if it's Qt problem or 'libresolv' problem (I don't know what's even libresolv).

    Here's the profiler message.

    Profiler message image


  • Lifetime Qt Champion

    Which version of libresolv is it exactly ?

    AFAIK, that's the library that currently implements the name resolution and related stuff on Linux style OSs.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.