Hrrmmm shouldn't those lines be...

Russ Allbery rra at stanford.edu
Sat Sep 9 00:07:35 UTC 2000


I think the summary here is that the &'s aren't the source of the problem,
although one can argue about coding style.  (Similarly, the assignment of
the result from the RENEW macro isn't the problem; p = p = expr(...) is
exactly the same as p = expr(...).)  The leak must be somewhere else.

The following is mostly pedantic standards stuff (yes, I'm a comp.std.c
reader), very ignorable if you're not interested.

Richard Irving <rirving at onecall.net> writes:

> Yes, relying upon a common cast to char works, but it is still poor
> form.

You *have* to rely on a cast for any call to memcmp() or memcpy() or the
like; those functions take void * and operate on bytes, so unless you're
passing in a pointer to a char *, it's doing (explicitly allowed by the
standard) casts behind the scenes.  INN assumes ANSI C (we've dropped
support for K&R compilers completely), and ANSI C says that you can
address any object by using a char * and that you don't have to explicitly
cast arguments to prototyped functions (and in fact doing so is not
recommended).

> There was a time when we flipped unsigned 32bit Ints into pointers and
> back, as a common practice. When 64 bit systems came around, we learned
> the error of our ways....sloppy.

I agree, but that's explicitly implementation-defined in the standard,
whereas a language in which you can't pass a pointer to an array to memcmp
and have it do the right thing (treating the array as a byte string) is
some language other than C.

Pointers really aren't very magical in C.  The standard allows for certain
fairly limited amounts of magic, but the requirement that you be able to
address any object by casting the pointer to a char * limits the amount of
allowable magic quite a bit.  It's a pretty dramatically different picture
than with a lot of other languages (and is one of the reasons why I
personally prefer to write in C).

> All I can say is I don't think this would have compiled in 89.  At least
> not without warnings... or errors.

> Current True64/Digital compilers treat it as a warning, as is...  (The
> -reason- I chose the word "undefined", BTW)

Which compilation mode are you using?  Tru64 4.0F, at least, defaults to
K&R mode, which isn't what you want when compiling most current software
including INN.

Tru64 4.0F has no problems in strict ANSI compliance mode (although note
that other parts of INN probably won't compile properly in strict
compliance mode at present; I'm working on that -- in the meantime, the
default relaxed mode of -std should be fine):

tru64-build:~> cc -std1 -w0 -o testing testing.c 
tru64-build:~> uname -a
OSF1 tru64-build V4.0 1229 alpha

It does warn in K&R mode (-std0), but as I said, INN doesn't support K&R
compilers.

(Test program is at the end of this message.)

>> "&array[0]" is completely equivalent to "array" when used as an
>> argument to a function, yes.

> To a function that cast the pointer to type char, or void, anyway.

I believe "array" is completely equivalent to "&array[0]" when passed as
an argument to *any* function.  Arrays used as arguments to functions
decay into a pointer to the first element of the array.

> But the real question is &array = &array[0], and that is -not- always
> true, do to the differing scalars, correct ?

&array and &array[0] are not completely equivalent syntactic pointers, no;
the difference is noticeable for pointer arithmetic, among other things.
However, &array == &array[0], so whenever you're treating the pointers as
pointers to raw bytes, either construct is equally valid.

> Now, if only the current version of this code could stay up and running
> for 24 hours... without nursing... I would be more inclined to listen to
> these arguments.

> In the meantime, we stand around debating an Ivory tower point, when we
> probably should be cleaning up code, eh?

Yup, agreed.

Test program, for the curious:

#include <stdio.h>
#include <string.h>

struct test {
    char array[50];
};

int main(void) {
    struct test test;

    printf("%lx %lx\n", (unsigned long) test.array,
           (unsigned long) &test.array);
    memset(&test.array, 0, sizeof(test.array));
    printf("%d\n", memcmp(&test.array, test.array, sizeof(test.array)));
    return 0;
}

Compiles with no warnings or problems with Solaris cc -Xc, Tru64 4.0F
cc -std1 -w0, or gcc -ansi -pedantic -Wall -W.  (It's my goal to
eventually get all of INN to compile cleanly with at *least* gcc -pedantic
-Wall -W.)

-- 
Russ Allbery (rra at stanford.edu)             <http://www.eyrie.org/~eagle/>



More information about the inn-workers mailing list