Thread: Problem with PQexecPrepared

Problem with PQexecPrepared

From
David Stanaway
Date:
Hi,

I am having a problem with a compiler warning using PQexecPrepared.
It is with the paramValues argument.

warning: passing arg 4 of `PQexecPrepared' from incompatible pointer
type

The type I am passing is a char** and it is expecting const char* const*

The parameters I am passing in a generated at runtime so I can supply a
const pointer. Am I missing something? Also, does someone have an
example using PQexecPrepared or PQexecParams using non-text params?

-- 
David Stanaway <david@stanaway.net>


Re: Problem with PQexecPrepared

From
"Jeroen T. Vermeulen"
Date:
On Wed, Jun 09, 2004 at 04:44:12PM -0500, David Stanaway wrote:
> The type I am passing is a char** and it is expecting const char* const*

I'm not sure I understand your question entirely, so forgive me if I'm
telling you things you already know...
The C type system needs to be strict here to guard against the case where
people try pass a "char **" argument to a "const char **" parameter.

Why is that a problem?

Because the function might try to insert a "const char *" into the array,
thinking it got passed an array of "const char *"s.  But after the function
returned, the caller might overwrite the actual string this pointer pointed
to because it never told the function that the chars were to be kept const.
This is a case where "adding a const" is not type-safe.

Not that it would be a problem here, because the array itself is const
and so the function could never write its own pointer into it.  I think
it's one of those rare situations where a cast is justified.


> The parameters I am passing in a generated at runtime so I can supply a
> const pointer.

Generating something at runtime doesn't mean you can't have a const pointer
to it.  Declaring the thing a pointer points to "const" is a promise that
you won't use the pointer to modify that thing.  Which doesn't mean that
it can't be modified through another pointer!


Jeroen



Re: Problem with PQexecPrepared

From
David Stanaway
Date:
On Wed, 2004-06-09 at 17:21, Jeroen T. Vermeulen wrote:
> On Wed, Jun 09, 2004 at 04:44:12PM -0500, David Stanaway wrote:
>  
> > The type I am passing is a char** and it is expecting const char*
const*

> Not that it would be a problem here, because the array itself is const
> and so the function could never write its own pointer into it.  I
think
> it's one of those rare situations where a cast is justified.

Thanks for the clarification. I thought it was odd to have to cast to a
const in this case. I changed the call like such:
 res = PQexecPrepared(serverp->connection,       serverp->queryps[BILLING_INSERTROUTED]->prephandle,       nparm,(const
char*const*)parms,NULL,NULL,1);
 

If the prototype had been for const char** I would not have needed to
change anything, the API author I guess is being thorough.

-- 
David Stanaway <david@stanaway.net>


Re: Problem with PQexecPrepared

From
Tom Lane
Date:
David Stanaway <david@stanaway.net> writes:
> On Wed, 2004-06-09 at 17:21, Jeroen T. Vermeulen wrote:
>> Not that it would be a problem here, because the array itself is const
>> and so the function could never write its own pointer into it.  I
>> think it's one of those rare situations where a cast is justified.

> If the prototype had been for const char** I would not have needed to
> change anything, the API author I guess is being thorough.

The author was me, and I didn't think I was creating any problems by
const-ifying the declaration :-(.  Jerome, are you sure this isn't
a compiler glitch?  I really have a problem with the notion that a
library routine can over-constify its input declarations...
        regards, tom lane


Re: Problem with PQexecPrepared

From
David Stanaway
Date:
On Jun 10, 2004, at 12:34 AM, Tom Lane wrote:

> David Stanaway <david@stanaway.net> writes:
>> On Wed, 2004-06-09 at 17:21, Jeroen T. Vermeulen wrote:
>>> Not that it would be a problem here, because the array itself is 
>>> const
>>> and so the function could never write its own pointer into it.  I
>>> think it's one of those rare situations where a cast is justified.
>
>> If the prototype had been for const char** I would not have needed to
>> change anything, the API author I guess is being thorough.
>
> The author was me, and I didn't think I was creating any problems by
> const-ifying the declaration :-(.  Jerome, are you sure this isn't
> a compiler glitch?  I really have a problem with the notion that a
> library routine can over-constify its input declarations...


Hi there,
The library prototype is fine. My GCC is gcc (GCC) 3.3.3 (Debian 
20040422).

Do you have an example of PQexecParams or PQexecPrepared using non text 
parameters?

-- 
David Stanaway <david@stanaway.net>



Re: Problem with PQexecPrepared

From
"Jeroen T. Vermeulen"
Date:
On Thu, Jun 10, 2004 at 01:34:12AM -0400, Tom Lane wrote:
> David Stanaway <david@stanaway.net> writes:
> > If the prototype had been for const char** I would not have needed to
> > change anything, the API author I guess is being thorough.
> 
> The author was me, and I didn't think I was creating any problems by
> const-ifying the declaration :-(.  Jerome, are you sure this isn't
> a compiler glitch?  I really have a problem with the notion that a
> library routine can over-constify its input declarations...

I don't think this is a compiler glitch.  The way the C type system works
(well, in its current form anyway) was thought out pretty well and I
wouldn't bet on gcc getting it wrong.  You can't hoist const qualifiers
across pointers, because the constness of a pointer is a very different
thing from the constness of whatever it points to.  The former can be
converted implicitly in this case, but the latter cannot because it's at
least as fundamental a property of the pointer's type as the "char" is.
It's hidden away a level too deep to meddle with, if you will.

This particular usage (converting "TYPE **" to "const TYPE *const *")
might probably have been allowed as a special case, but such exceptions
make for convoluted type systems and perhaps even paradoxes.  Compilers
used to be full of such ad-hockery IIRC, and the standardization process
got rid of it so that all compilers could implement a single, consistent
language.  And as the poem goes, there was dancing in the dock; and a
day of celebration was commanded in Bangkok.

I wouldn't say that the library routine over-constified the parameter
either.  Think about it: what other type could you possibly give it?
It's a char const *const * by nature, and there's no point in denying it.
Whether this problem turns up in practice probably depends a lot on one's
programming style:
const char **array = malloc(strings * sizeof(*array));for (n=0; n<strings; ++n){    char buf[100];    char *mystring;
int len;
 
    len = get_a_string(buf, 100);    array[n] = mystring = malloc(len);    strcpy(mystring,
buf);}pass_parameter(array);

Note how the strings are generated at runtime, but the array only sees
const char *'s.  The array itself may be nonconst, but that is the one
implicit conversion that is allowed while passing it as a parameter.


Jeroen