On Friday 01 February 2008, you wrote:
> Yes; but I still have to manually increment the size to an appropriate
> value each time I add a bigger string; plus I'm wasting space for all
> shorter strings (which applies more to bigger-than-two-element char
> arrays);

Actually, you're not always. The actual space occupied by a pointer to 
character is

sizeof(char*) + sizeof("literal");

This means that for 32-bit (best-case)

char *foo = "a" -> 4 + 2 = 6 bytes
char *foo = "ab" -> 4 + 3 = 9 bytes
char *foo = "abc" -> 4 + 4 = 8 bytes

char foo[] = "a" -> 2 bytes
char foo[] = "ab" -> 3 bytes
char foo[] = "abc" -> 4 bytes

By that reasoning, char foo[6] will _always_ take less or equal space than 
char *foo.
But 32-bit architectures are also dying beside embedded systems, which means 
that the most common case especially in the years to come will be 
sizeof(char*) == 8 (64-bit architectures), at which point char foo[10] will 
always be smaller or equal to char *foo.

Considering you get out with an indirection less, most of the time even 
wasting 8 more bytes per string is worth the change.

> The first solution makes good sense to me, particularly for its improved
> correctness; but fixing the second problem seems like a
> nano-optimization that doesn't bring sufficient efficiency benefits to
> outweigh its drawbacks in maintainability.

It is a micro-optimisation, I admit that, but it's not just the indirection 
the problem.

Pointers, and structures containing pointers, need to be runtime-relocated for 
shared libraries and PIC code (let's assume that shared libraries are always 
PIC, for the sake of argument). In these cases the data is written 
to .data.rel, or .data.rel.ro for costants (I'm talking ELF here, other 
output formats most likely have something like that), which are copy-on-write 
sections. Without prelinking, these sections will be copied right at the 
start of the program, and when copied, they are no more shared between 
processes. Which means they'll be using pages of private memory on the 
various processes.

It is a minor thing for wget as it's not a shared library, but a 
fire-and-forget program, so even for security people using PIE it's far from 
being a big hit. It's more important for shared libraries though, especially 
because shared libraries can't always be prelinked properly. See also 
http://farragut.flameeyes.is-a-geek.org/articles/2008/01/01/reminding-a-weakness-of-prelink

Now, glib comes to the point of using the method that Mart described in the 
comments to my first blog ( 
http://farragut.flameeyes.is-a-geek.org/articles/2007/12/19/array-of-pointers-and-array-of-arrays
 ) 
and I quoted on the second ( 
http://farragut.flameeyes.is-a-geek.org/articles/2008/01/01/some-more-about-arrays-of-strings
 ) 
to avoid the increase-the-size and waste-the-space game, but making it a 
quite bigger, IMHO, maintenance problem. I haven't seen enough use yet for 
this to be a royally good idea, but I'm thinking of trying that out with 
xine-lib soon enough (without the second array, if the access can be done 
sequentially instead of randomly).

-- 
Diego "Flameeyes" Pettenò
http://farragut.flameeyes.is-a-geek.org/

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to