cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: http headers free and multi

From: Brian Dessent <brian_at_dessent.net>
Date: Fri, 13 Oct 2006 17:58:04 -0700

Mohun Biswas wrote:

> As to your specific question "how would the application know what data
> to request from libcurl in order to free it after an operation?", I'm
> baffled as to why you'd ask. Perhaps I misunderstand. How does that
> question differ from "how would the application know what URL to use?"
> The application knows what data it has allocated and needs to free. The
> distinction I'd make is this: the FACT that I malloc an error buffer is
> known at compile time. The ADDRESS of the buffer is only known at
> runtime. Knowing things at compile time is better/easier/safer/more robust.

*You* know that you malloc'd a buffer but libcurl does not. All it
knows is that it's given a char *, but that could be any of a number of
things:

- a buffer on the stack that will automatically be reclaimed when the
code goes out of scope
- a string constant in a read-only segment (in the case of e.g.
CURLOPT_URL)
- a buffer malloc'd on the heap, but one which will be used across
multiple transfers and so needn't be free'd each time
- a buffer on the heap that does need to be free'd when the curl handle
is closed

In other words, libcurl can not assume to know the nature of the buffer,
and pretending that it can will just result in crashes, programmer
confusion, etc. All it can do is defer to the knowledge of the
programmer, and that's what CURLOPT_PRIVATE is.

Now you could potentially make the case for adding an API to directly
retrieve those CURLOPT_URL and CURLOPT_ERRORBUFFER pointers, but what
really are the conceptual differences between:

typedef struct {
  char *urlbuf;
  char *errorbuf;
} mybuffers;

...

mypointers bufs;
bufs.urlbuf = malloc ( ... );
bufs.errorbuf = malloc ( ... );

...

curl_easy_setopt (handle, CURLOPT_URL, bufs.urlbuf);
curl_easy_setopt (handle, CURLOPT_ERRORBUFFER, bufs.errorbuf);
curl_easy_setopt (handle, CURLOPT_PRIVATE, (char *)&bufs);
curl_easy_perform (handle);

...

curl_easy_getinfo (handle, CURLINFO_PRIVATE, &bufs);
free (bufs.urlbuf);
free (bufs.errorbuf);

---- and this ---

urlbuf = malloc ( ... );
errorbuf = malloc ( ... );

...

curl_easy_setopt (handle, CURLOPT_URL, urlbuf);
curl_easy_setopt (handle, CURLOPT_ERRORBUFFER, errorbuf);
curl_easy_perform (handle);

...

char *foo;
curl_easy_getinfo (handle, CURLINFO_GETPTR_URL, &foo);
free (foo);
curl_easy_getinfo (handle, CURLINFO_GETPTR_ERRORBUF, &foo);
free (foo);

See? In both cases the programmer had to do basically the same
bookkeeping, because libcurl cannot assume that anything needs to be
free'd. The only question is whether this bookkeeping is done by
passing a user defined CURLINFO_PRIVATE struct or through repetitive
calls to (fictional) CURLINFO_GETPTR_*. The programmer still has to
explicitly enumerate this knowledge of what to free.

Brian
Received on 2006-10-14