Can a pointer passed to sucessful realloc be used later in pointerarithmetic?

F

Francois Grieu

Can a pointer passed to sucessful realloc be used later in pointer
arithmetic? This would sometime help fix pointers that pointed into
the original block, so that they point properly in the new one.

In other words, is the following program conformant?

#include <stdlib.h>
int main(void)
{
char *p,*q,*r;
// allocate a block of 40 chars
if ((p = malloc(40))==NULL)
return EXIT_FAILURE;
// set q to point 20 chars into the block
q = p+20;
// poke an 'x' at q
*q = 'x';
// extend the block to 80 chars
if ((p = realloc((r=p),80))==NULL)
{
free(r);
return EXIT_FAILURE;
}
// the realloc() may have made q invalid, fix it
q = (q-r)+p;
// display the 'x'
printf("%c\n",*q);
free(p);
return EXIT_SUCCESS;
}

The statement q = (q-r)+p; is questionable since q and r are
pointers into a block that was passed to a sucessful realloc. I guess
q += p-r; is even more likely to turn wrong.

TIA for your comments, preferably with reference to the text of some C
standard.

Francois Grieu
 
W

Willem

Francois wrote:
) Can a pointer passed to sucessful realloc be used later in pointer
) arithmetic? This would sometime help fix pointers that pointed into
) the original block, so that they point properly in the new one.
)
) In other words, is the following program conformant?
)
) #include <stdlib.h>
) int main(void)
) {
) char *p,*q,*r;
) // allocate a block of 40 chars
) if ((p = malloc(40))==NULL)
) return EXIT_FAILURE;
) // set q to point 20 chars into the block
) q = p+20;
) // poke an 'x' at q
) *q = 'x';
) // extend the block to 80 chars
) if ((p = realloc((r=p),80))==NULL)
) {
) free(r);
) return EXIT_FAILURE;
) }
) // the realloc() may have made q invalid, fix it
) q = (q-r)+p;
) // display the 'x'
) printf("%c\n",*q);
) free(p);
) return EXIT_SUCCESS;
) }
)
) The statement q = (q-r)+p; is questionable since q and r are
) pointers into a block that was passed to a sucessful realloc. I guess
) q += p-r; is even more likely to turn wrong.

To be on the safe side, you could do this:

...
size_t q_offset = (q - r);
... realloc(...)
q = p + q_offset;
...

Which, I think, should be perfectly valid.
The type (size_t) of q_offset is the only thing that might be an issue.
(Is ptrdiff_t standard C ?)


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
B

Ben Bacarisse

Francois Grieu said:
Can a pointer passed to sucessful realloc be used later in pointer
arithmetic?
#include <stdlib.h>
int main(void)
{
char *p,*q,*r;
// allocate a block of 40 chars
if ((p = malloc(40))==NULL)
return EXIT_FAILURE;
// set q to point 20 chars into the block
q = p+20;
// poke an 'x' at q
*q = 'x';
// extend the block to 80 chars
if ((p = realloc((r=p),80))==NULL)
{
free(r);
return EXIT_FAILURE;
}
// the realloc() may have made q invalid, fix it
q = (q-r)+p;
// display the 'x'
printf("%c\n",*q);
free(p);
return EXIT_SUCCESS;
}

The statement q = (q-r)+p; is questionable since q and r are
pointers into a block that was passed to a sucessful realloc.

Yes. This is one of those "in theory" problems. Once the old object
has been deallocated, the guarantees the standard gives you for
pointer arithmetic (on the old pointers) vanish. I have never used a
system where the above will go wrong, but it is not guaranteed by the
standard. It might, for example, go wrong on some clever future
hardware where pointers can be invalidated when the objects they point
to "go away".

Such code is not uncommon (I am sure I've seen it several times) so
there may have been some guidance from the C committee about such
situations. If there has been, you'll hear about it soon right here.
Ditto if I have got the above wrong!
I guess
q += p-r; is even more likely to turn wrong.

Yes, this is "even more wrong" if that makes any sense. p and q don't
point into the same object so the subtraction is undefined.
 
W

WANG Cong

Can a pointer passed to sucessful realloc be used later in pointer
arithmetic?
#include <stdlib.h>
int main(void)
{
char *p,*q,*r;
// allocate a block of 40 chars
if ((p = malloc(40))==NULL)
return EXIT_FAILURE;
// set q to point 20 chars into the block q = p+20;
// poke an 'x' at q
*q = 'x';
// extend the block to 80 chars
if ((p = realloc((r=p),80))==NULL)
{
free(r);
return EXIT_FAILURE;
}
// the realloc() may have made q invalid, fix it q = (q-r)+p;
// display the 'x'
printf("%c\n",*q);
free(p);
return EXIT_SUCCESS;
}

The statement q = (q-r)+p; is questionable since q and r are pointers
into a block that was passed to a sucessful realloc.

Yes. This is one of those "in theory" problems. Once the old object
has been deallocated, the guarantees the standard gives you for pointer
arithmetic (on the old pointers) vanish. I have never used a system
where the above will go wrong, but it is not guaranteed by the standard.
It might, for example, go wrong on some clever future hardware where
pointers can be invalidated when the objects they point to "go away".

Such code is not uncommon (I am sure I've seen it several times) so
there may have been some guidance from the C committee about such
situations. If there has been, you'll hear about it soon right here.
Ditto if I have got the above wrong![/QUOTE]

C99 states that the new pointer got via realloc "may have the same
value as a pointer to the old object", so it can't guarantee.

Yes, this is "even more wrong" if that makes any sense. p and q don't
point into the same object so the subtraction is undefined.

I assume you meant "p and r don't ..."?

Agreed.
 
B

Ben Bacarisse

WANG Cong said:
Yes. This is one of those "in theory" problems. Once the old object
has been deallocated, the guarantees the standard gives you for pointer
arithmetic (on the old pointers) vanish. I have never used a system
where the above will go wrong, but it is not guaranteed by the standard.
It might, for example, go wrong on some clever future hardware where
pointers can be invalidated when the objects they point to "go away".

Such code is not uncommon (I am sure I've seen it several times) so
there may have been some guidance from the C committee about such
situations. If there has been, you'll hear about it soon right here.
Ditto if I have got the above wrong!

C99 states that the new pointer got via realloc "may have the same
value as a pointer to the old object", so it can't guarantee.[/QUOTE]

Agreed, but I don't see that that makes matters any worse. One can
imagine an implementation in which it works only when the returned
pointer in the same as the original!
I assume you meant "p and r don't ..."?

Yes, thank you.
 
B

Barry Schwarz

Can a pointer passed to sucessful realloc be used later in pointer
arithmetic? This would sometime help fix pointers that pointed into
the original block, so that they point properly in the new one.

In other words, is the following program conformant?

#include <stdlib.h>
int main(void)
{
char *p,*q,*r;
// allocate a block of 40 chars
if ((p = malloc(40))==NULL)
return EXIT_FAILURE;
// set q to point 20 chars into the block
q = p+20;
// poke an 'x' at q
*q = 'x';
// extend the block to 80 chars
if ((p = realloc((r=p),80))==NULL)

If p does not equal r (meaning the realloc was not accomplished in
place and the original 40 bytes were copied to the new area), C99
guarantees that the value in r magically becomes indeterminate
6.2.4-2).
{
free(r);
return EXIT_FAILURE;
}
// the realloc() may have made q invalid, fix it
q = (q-r)+p;

And you are not allowed to compute with an indeterminate value (J.2).
// display the 'x'
printf("%c\n",*q);
free(p);
return EXIT_SUCCESS;
}

The statement q = (q-r)+p; is questionable since q and r are
pointers into a block that was passed to a sucessful realloc. I guess
q += p-r; is even more likely to turn wrong.


Remove del for email
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top