curl-library
Re: Memory leak if FTP server responds "530 Login incorrect"
Date: Mon, 11 Dec 2006 19:46:13 +0200
> I then run the example and use 'memanalyze.pl' to check for leaks:
> $ memanalyze.pl memdump
>$
> Ie, it finds none. I even did a make clean and rebuild just to be extra
sure
> my build has nothing "weird" in it, but still no leak.
> It makes me interested in what the difference is between your
build/version
> and mine!
Actually to find memory leaks I'm using some memory profiler tool on Win,
not your memdebug module. So unfortunately I cannot say why leaks are not
detected in your environment.
To prove that there are memory leaks I modified a test program to run
a lot of FTP fetches sequentially. Then I ran it with performance monitor.
Attached you can see a chart <memoryleak.pdf> which shows memory usage
of test program during execution of 10 000 000 FTP fetches.
Here is a code of test program:
//--------------------------------------------------------------------------
-
#include "curl/curl.h"
#ifndef TRUE
#define TRUE 1
#endif
struct FtpFile {
char *filename;
FILE *stream;
};
int my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream)
{
struct FtpFile *out=(struct FtpFile *)stream;
if(out && !out->stream) {
/* open file for writing */
out->stream=fopen(out->filename, "wb");
if(!out->stream)
return -1; /* failure, can't open file to write */
}
return fwrite(buffer, size, nmemb, out->stream);
}
int test( const char * cszURL )
{
CURL* handle;
CURLM* multi_handle;
int still_running; /* keep number of running handles */
struct FtpFile ftpfile={
"test.txt", /* name to store the file as if succesful */
NULL
};
multi_handle = curl_multi_init();
handle = curl_easy_init();
CURLMcode code = curl_multi_add_handle( multi_handle, handle );
curl_easy_setopt(handle, CURLOPT_URL, cszURL);
/* Define our callback to get called when there's data to be written */
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, my_fwrite);
/* Set a pointer to our struct to pass to the callback */
curl_easy_setopt(handle, CURLOPT_WRITEDATA, &ftpfile);
/* Switch on full protocol/debug output */
curl_easy_setopt(handle, CURLOPT_VERBOSE, FALSE);
// speed up the test
curl_easy_setopt(handle, CURLOPT_NOBODY, TRUE);
/* we start some action by calling perform right away */
while(CURLM_CALL_MULTI_PERFORM ==
curl_multi_perform(multi_handle, &still_running));
while(still_running) {
struct timeval timeout;
int rc; /* select() return code */
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
/* set a suitable timeout to play around with */
timeout.tv_sec = 1;
timeout.tv_usec = 0;
/* get file descriptors from the transfers */
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
/* In a real-world program you OF COURSE check the return code of
the
function calls, *and* you make sure that maxfd is bigger than -1
so
that the call to select() below makes sense! */
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
switch(rc) {
case -1:
/* select error */
still_running = 0;
printf("select() returns error, this is badness\n");
break;
case 0:
default:
/* timeout or readable/writable sockets */
while(CURLM_CALL_MULTI_PERFORM ==
curl_multi_perform(multi_handle, &still_running));
break;
}
}
curl_multi_remove_handle( multi_handle, handle );
curl_easy_cleanup( handle );
curl_multi_cleanup( multi_handle );
if(ftpfile.stream)
fclose(ftpfile.stream); /* close the local file */
return 0;
}
int main(int argc, char* argv[])
{
int nCount = 1;
if ( argc > 1 ) {
nCount = atoi(argv[1]);
}
curl_global_init(CURL_GLOBAL_DEFAULT);
printf("Performing %d iteration(s)...\n", nCount);
for (int i = 0; i < nCount; i++) {
test(
"ftp://ftp.sunet.se/pub/www/utilities/curl/curl-7.9.2.tar.gz" );
}
printf("Done\n");
curl_global_cleanup();
return 0;
}
//--------------------------------------------------------------------------
-
- application/pdf attachment: memoryleak.pdf