Hi David, hi Andrew,
One other thing I just thought of: GCC has a history of very smart
extensions to C that allow to write faster and more elegant code. If I
look at my code, there are mostly two sources of 'dirty hacks' left. One
that could be fixed easily is the 'void** pointer problem', that
clutters my code with nasty explicit type casts:
A simple example is the function freesetnull, that frees a pointer and
sets it NULL (ptradd is a pointer address):
void freesetnull(void **ptradd)
{ free(*ptradd);
*ptradd=NULL; }
Normally, good style encourages using static inline functions instead of
macros, but here I would go for a macro:
freesetnull(_p) do { free(_p); _p = NULL; } while (0)
Note the slight change in the semantics - you pass the pointer, not a
pointer to the pointer.
I expect this will also have the bonus of improving the speed of the
resulting program - and possibly even of the compilation.
Many thanks, but this was really just the most simple example to
illustrate how GCC's prohibition to pass a 'pointer to any pointer' to a
function expecting a void** causes more problems than it solves. In your
case, you are forced to use a macro (with the usual side-effects
problem) instead of a safe 'static inline' to circumvent the problem.
But my code is full of cases that go beyond what can reasonably be done
with macros.
Just one more complicated example:
A function that loads a binary file from disk and allocates the required
memory to store the file contents, returning the number of bytes read.
dstadd is the address where the newly allocated pointer is stored:
int dsc_loadfilealloc(void *dstadd,char *filename)
{ int read,size;
FILE *fb;
if ((fb=fopen(filename,"rb")))
{ size=dsc_filesize(filename);
*(void**)dstadd=mem_alloc(size);
read=dsc_readbytes(*(void**)dstadd,fb,size);
*(void**)dstadd=mem_realloc(*(void**)dstadd,read);
fclose(fb);
return(read); }
*(void**)dstadd=NULL;
return(0); }
Again, nasty casts all over the place, which would all disappear if GCC
allowed me to write
int dsc_loadfilealloc(void **dstadd,char *filename)
which could then be used to load anything from text files to an array of
'struct foo'.
Regarding compile time, modern gcc has "-funit-at-a-time" and
"-ftop-level-reorder" enabled by default, even with no optimisation
enabled. These could take time on such a huge source code. Try compiling
with "-fno-unit-at-a-time" (which implies "-fno-toplevel-reorder").
Many thanks, tried that and the time at -O !increased! (I am writing
this from a slower computer) from 6 minutes 38 to 7 minutes. BTW, the
time with -O0 is just 17 seconds.
And to Andrew Haley:
>> To me, that just looks like a remnant from the ancient past that hinders
>> the future. On the other hand, my feeling tells me that this patch would
>> not be accepted, that's why I'm asking for my chances in advance ;-)
>
> Not at all high. See Type-Based Alias Analysis
> <http://www.drdobbs.com/cpp/type-based-alias-analysis/184404273>
> for one reason.
Thanks, I read the article, but didn't really see how forbidding a
function with argument void** to accept a pointer to any pointer helps
with aliasing.
If it's perfectly normal that a function with argument void* accepts any
pointer, then a function with argument void** should accept a pointer to
any pointer by analogy, without having additional aliasing problems, no?
All the best,
Elmar
--
Elmar Krieger, PhD
YASARA Biosciences & CMBI Outstation Austria
Wagramer Strasse 25/3/45
1220 Vienna
Austria/Europe
www.YASARA.org