Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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