cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: http headers free and multi

From: Mohun Biswas <m_biswas_at_mailinator.com>
Date: Sat, 14 Oct 2006 00:10:32 -0400

Brian Dessent wrote:
> 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.

Yes. You seem to have missed a lot of context. I am quite explicitly not
asking for libcurl to free data that I have allocated; I understand what
you say above and in fact stated as much in my prior post. I've been
using libcurl for 2+ years now (and C for 20+) and I think I understand
the basics reasonably well.

> 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:

Not only could I *potentially* make that case, I *did* make that case.

> ...
>
> See? In both cases the programmer had to do basically the same
> bookkeeping, because libcurl cannot assume that anything needs to be
> free'd.

Please read my post again.

> 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_*.

Other questions include whether two copies of each pointer are kept. And
whether the application programmer has to manage the allocation of data
to manage allocations of data. All the stuff I said before.

This isn't a huge deal. I don't mean to say I can't stuff the required
data into CURLOPT_PRIVATE; I can and do, and I'm sure most other
programmers can too. I'd just like to see someone engage seriously and
lucidly on the question of why a solution which requires two copies of
the data is more elegant than one needing just a single copy.

BTW, the solution can be cleaner than "CURLINFO_GETPTR_*". All these
values are set with "curl_easy_setopt(CURLOPT_FOO)". Why can't they be
retrieved with "curl_easy_getopt(CURLOPT_FOO). No new constants need be
invented.

This isn't new invention here; it's standard getter/setter stuff and
it's good for all the reasons getter/setter stuff is good elsewhere.

> The programmer still has to explicitly enumerate this knowledge of what to free.

Of course. Let me try one more time to make my point. Take the simplest
example: I'm malloc-ing an error buffer and, since I don't need
CURLOPT_PRIVATE for anything else, I can stick the to-be-freed value in
there directly:

     char *errbuf = malloc(CURL_ERROR_SIZE);
     curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
     curl_easy_setopt(curl, CURLOPT_PRIVATE, errbuf);

then the handle gets passed around and used for a while. Later, in a
different function it gets freed:

     char *ptr;
     curl_easy_getinfo(curl, CURLINFO_PRIVATE, &ptr);
     free(ptr);

Notice that (a) there are two copies of 'errbuf' and (b) the freeing
code block is utterly opaque in terms of WHAT it's freeing. Whereas if
we free the result of

     curl_easy_getopt(CURLOPT_ERRORBUFFER);

then the lifespan of the error buffer is better documented before a
single comment is written.

MB
Received on 2006-10-14