Re: Realloc and pointer arithmetics
- From: Flash Gordon <spam@xxxxxxxxxxxxxxxxxx>
- Date: Fri, 18 Apr 2008 18:42:11 +0100
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
.
- Follow-Ups:
- Re: Realloc and pointer arithmetics
- From: Hallvard B Furuseth
- Re: Realloc and pointer arithmetics
- From: Chris Torek
- Re: Realloc and pointer arithmetics
- References:
- Realloc and pointer arithmetics
- From: lithiumcat
- Realloc and pointer arithmetics
- Prev by Date: Re: sizeof in old C compilers
- Next by Date: Re: sizeof in old C compilers
- Previous by thread: Realloc and pointer arithmetics
- Next by thread: Re: Realloc and pointer arithmetics
- Index(es):
Relevant Pages
|