cURL / Mailing Lists / curl-library / Single Mail

curl-library

known memory leak in simple easy calls in version 17?

From: Max L. Eidswick <max_at_eidswick.com>
Date: Wed, 20 Aug 2008 22:03:43 -0600

I have a definite memory leak happening with a simple test (source below). I question whether this is a curl issue or not as I was
confident up until now that the version 17 code for these simple easy calls is stable. This is too simple a problem to exist in
that mature code base (I think).

Please take a quick look at the test win32 proc to see if there is anything obvious. If I comment out the call to easy perform
there is no memory increase in the test process. If the call to easy perform is there is seems to burn through about 512-1024 bytes
per call.

If I remove the write buffering, there is no change.

If I comment out the call to easy perform there is not memory gain by the test process.

Are there any known memory leak issues like this in the version 17 code?

This test is performing a complete global init and cleanup every loop, so perhaps that is the problem, although this test was
supposed to prove that our memory leak in this test app was not in the curl code.

Thanks,

Max

----- snip

// =====================================================================
// RPCURLTst17a proc
//
// this proc is for testing curl easy code 7.17.1 to identify a suspect
// memory leak during perform curl call ...
//
// =====================================================================
ULONG RPCURLTst17a ( UCHAR *szURL ) // ping URL, return codes tbd
{
        CURL *curlhPing ; // libcurl ping easy handle
        CURLcode res ; // result code from libcurl

        // setup memory structures for memory
        struct MemoryStruct writeBuffer = { '\0', 0, 0 } ;
        BOOL bCurlGlobalInitDone = FALSE ; // set when global init done

        if ( !bCurlGlobalInitDone )
        {
                // -------------------------------------------------------------
                // setup libcurl global info for win32, global cleanup on exit
                // -------------------------------------------------------------
                if ( curl_global_init ( CURL_GLOBAL_ALL | CURL_GLOBAL_WIN32 ) )
                {
                        strcpy ( ucCURLErrorBuffer, // defined globally in rpv7.h
                                "libcurl global init error in RPCommsPing" ) ;
                        return ( CURLGLOBALINITFAIL ) ; // ^^^^^^^^^^^^^^^^^^^^^^^^^
                } // end of call to curl global init failed

                // -------------------------------------------------------------
                // CURL global initialization is now done or we exited with a
                // failure code
                // -------------------------------------------------------------

        } // end of if global init not done

        // -----------------------------------------------------------------
        // ok, curl global init was successful, so set flag to curl global
        // cleanup on exit
        // -----------------------------------------------------------------
        bCurlGlobalInitDone = TRUE ; // make sure ut global cleanup on exit

        // -----------------------------------------------------------------
        // now, setup the test operation
        // -----------------------------------------------------------------
        curlhPing = curl_easy_init ( ) ; // get curl handle
        if ( !curlhPing ) // zero means no handle, failed
        {
                // failed to get easy handle, so global cleanup and ABEND
                if ( bCurlGlobalInitDone)
                {
                        curl_global_cleanup ( ) ; // clean up environment
                        bCurlGlobalInitDone = FALSE ;
                }

                strcpy ( ucCURLErrorBuffer, "libcurl easy init error" ) ;
                return ( CURLEASYINITFAIL ) ; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

        } // end of if !curl call to curl init failed

        // -----------------------------------------------------------------
        // set up a call back to process the website returned data in
        // bytes terminated by a null and storage for the write function
        // -----------------------------------------------------------------
        curl_easy_setopt (
                                curlhPing, // ping curl handle
                                CURLOPT_WRITEFUNCTION, // setup write callback
                                RPCommsCurlWriteDataToMemory // our write callback
                                                ) ;

        // -----------------------------------------------------------------
        // as the write function picks up bytes have it copied to our
        // write buffer with a null termination byte (see
        // WriteDataToMemory proc for details)
        // -----------------------------------------------------------------
        curl_easy_setopt (
                                curlhPing,
                                CURLOPT_WRITEDATA,
                                &writeBuffer
                                                ) ;

        // -----------------------------------------------------------------
        // if there are any errors, make sure we know what libcurl says
        // is going on in a global buffer
        // -----------------------------------------------------------------
        curl_easy_setopt (
                                curlhPing,
                                CURLOPT_ERRORBUFFER,
                                ucCURLErrorBuffer
                                                ) ;

        // -----------------------------------------------------------------
        // curl fails on 400+ error codes from the server - it's unclear
        // if this does anything useful for our ping example, but it is
        // in the planned production design, so it is here too ...
        // -----------------------------------------------------------------
        curl_easy_setopt ( curlhPing, CURLOPT_FAILONERROR, TRUE ) ;

        // -----------------------------------------------------------------
        // setup our test URL every time for this test
        // -----------------------------------------------------------------
        curl_easy_setopt ( // setup URL to touch
                                curlhPing,
                                CURLOPT_URL,
                                szURL // URL passed in RPCommsPing proc
                                                ) ;

        // -----------------------------------------------------------------
        // check the msecs before and after the call to easy perform in
        // global ulPingPerformMSecs
        // -----------------------------------------------------------------
        res = curl_easy_perform ( curlhPing ) ; // <<<<< ----- PING !

        // -----------------------------------------------------------------
        // cleanup memory allocation by write callback
        if ( writeBuffer.memory )
                free ( writeBuffer.memory ) ;

        writeBuffer.lastSize = 0 ;
        writeBuffer.memory = 0 ;
        writeBuffer.size = 0 ;

        // -----------------------------------------------------------------
        // cleanup after libcurl
        // -----------------------------------------------------------------
        curl_easy_cleanup ( curlhPing ) ; // end of easy session

        // -------------------------------------------------------------
        // free up global resources -
        // -------------------------------------------------------------
        if ( bCurlGlobalInitDone ) // do global cleanup before exiting
        {
                curl_global_cleanup ( ) ; // clean up environment
                bCurlGlobalInitDone = FALSE ; // show we are no longer init'd
        }

        return ( res ) ; //

} // end of RPCommsPing proc
// =====================================================================
Received on 2008-08-21