Re: Realloc and pointer arithmetics



lithiumcat@xxxxxxxxx wrote, On 18/04/08 16:33:
Hi,

maybe you remember me, some time ago I asked about how to store an
integer value into a void*, and I learned that doing pointer
arithmetic yeilding a pointer outside of an object (except the one-
after-last thingy) is undefined behaviour.

I remember there was a discussion about this.

Actually I was trying to associate a function pointer with a key,
through an AVL tree that managed void* data. Function pointers can't
be stored in void* (that is, the standard does not garantee it works),

Well, the C standard does not. However, if you limit yourself to a suitable subset of C implementations you might find another standard that does. For instance, I believe that the Posix standard provides this guarantee, so it is possible. Note that as you are going beyond what the C standard guarantees you need to select which implementations you are interested in and select a method common to them.

so I stored them in a dynamic array and that was the index in said
array that I wanted to store in the void* of the tree.

My frist thought was actually to store into the tree pointers to array
elements, instead of their index. The problem is, the array being
dynamic, realloc() might change its location, and then all the
pointers in my tree become invalid.

OK, you have avoided the first trap.

So I thought about putting in my tree pointers to array elements, and
then when realloc() changes the base, correct all the nodes of the
tree accordingly. Something like that:

fnptr* oldbase = base_of_dynamic_fnptr_array;
increase_dynamic_array_size();
fnptr* newbase = base_of_dynamic_fnptr_array;
if (oldbase != newbase)
for (void** storage_location in the tree for all nodes) {
fnptr* oldptr = *storage_location;
int index = oldptr - oldbase;
*storage_location = newbase + index; }

From what I googled this is the usual way of dealing with pointers to
elements inside a realloc()ed array, and I think it works just fine on
many platforms.

But is this garanteed to work?

No.

According to my (poor) understanding of
the standard, if realloc() returns the original pointer, then oldbase
and newbase are both valid pointers which compare equal, so there is
no problem.

Correct.

But if realloc() changes the location of the dynamic
array, oldbase becomes an invalid pointer. I think in that case
oldbase is garanteed to compare unequal with newbase, which is a valid
pointer, but using it to compute "index" is undefined, right?

No, it is *not* guaranteed to compare unequal. Just evaluating it invokes undefined behaviour and so could crash your program.

And if the above code is not garanteed to work by the standard, is
there any portable way of handling dynamic arrays moved by realloc()?
(besides never using pointers to elements inside a dynamic array)

The way to deal with it is to use indices rather than pointers.

Actually, for your problem as you need something beyond what the C standard guarantees I would be inclined to rely on the guarantees of Posix and the behaviour of Windows and just store the function pointers in the void* if that would cover all the required platforms. Then the code is far simpler.
--
Flash Gordon
.



Relevant Pages

  • Re: "<>", a relational operator?
    ... And in Standard C there are significant restrictions ... OTOH in BCPL and B pointers were ... has no whole array operations; if you want something done to all (or ... the Standard isn't vague at all -- this is specifically ...
    (comp.lang.fortran)
  • Re: Linked list or realloc()?
    ... > I'm currently doing a project that has a array that supposed to be ... > LinkedListNode as needed and use freeto destroy a node. ... around the nodes, you will sort the array of pointers, search the ... int cmp(const void *v1, const void *v2); ...
    (comp.lang.c)
  • Re: memory management
    ... I don't have a copy of the standard available to ... Accessing out of declared bounds of an array is ... floating-point and very occasionally pointers. ... This is called the 'struct hack', see 2.6 in the C FAQ at the usual ...
    (comp.lang.ada)
  • Re: C newbie in a jam
    ... Richard Heathfield skrev: ... void, not VOID ... The first is a pointer to an array of ROW x COL doubles. ... attempt to define an array of ROW x COL pointers to double - an attempt ...
    (comp.lang.c)
  • Re: Is it possible to make void * safer?
    ... array_push(array, (void*)data);} ... The cast to (void *) looks ... I was specifically demonstrating how to mimic template in C with macros. ... That's why I added the function pointers, ...
    (comp.lang.c)