free()'ing restrict'ed pointers

S

s0suk3

Hi,

A object to which there is a pointer that has been declared 'restrict'
is supposed to be accessed only through that pointer. So is it safe to
call free() with a restricted pointer? Does free() try to access what
in points to in some way?

Thanks,
Sebastian
 
S

santosh

Hi,

A object to which there is a pointer that has been declared 'restrict'
is supposed to be accessed only through that pointer. So is it safe to
call free() with a restricted pointer?
Yes.

Does free() try to access what
in points to in some way?

It most certainly accesses it's argument, but whether it accesses the
storage pointed to is not specified. In any case after calling free the
pointer object is left in an indeterminate state, and the storage
pointed at is no longer available. So it shouldn't matter to you
whether free accesses the storage or not.
 
B

Ben Bacarisse

A object to which there is a pointer that has been declared 'restrict'
is supposed to be accessed only through that pointer.

Hmmm.... A better (and I am sure this is not the last word on the
subject) is that objects that have a restrict qualified pointer to
them are only /modified/ via that pointer while it exists[1]. You can
access the value via other means, it is modifications that must be via
the pointer.
So is it safe to call free() with a restricted pointer?

Usually, yes.
Does free() try to access what in points to in some way?

I does not matter since it would be allowed to, at least by the
restrict keyword. It is possible that UB results at the exact moment
free is called in this daft code:

void *space = malloc(1);
void *restrict rp = space;
free(space); // are we modifying *rp? -- I don't know.

but that is very much an academic argument. This is fine:

void *restrict rp = malloc(1);
free(rp);

[1] This last bit plays fast a loose with the very precise definition
of the time during which the restrict restrictions apply, but it is
not a bad approximation to the truth.
 
C

christian.bau

Hi,

A object to which there is a pointer that has been declared 'restrict'
is supposed to be accessed only through that pointer. So is it safe to
call free() with a restricted pointer? Does free() try to access what
in points to in some way?

You are quoting incorrectly what "restrict" means: The data pointed to
may be accessed through the restrict pointer itself, or through a
pointer derived from that pointer. If you have a pointer "int
*restrict p" and call free (p), then the argument to free is derived
from p and is allowed to access the data as much as it likes.

Now what is wrong is the following:

int* p = malloc (100);
int* restrict q = p;

p [0] = 1;
free (q);

(the call free (q) is just as wrong as an assignment q [0] = 2 or just
reading q [0] would be).
 
C

christian.bau

void *space = malloc(1);
void *restrict rp = space;
free(space); // are we modifying *rp? -- I don't know.

The "restrict" keyword allows to compiler to rearrange loads and
stores. So if you used int* instead of void* and an assignment to *rp
before the call to free (), the compiler could move the assignment
past the call to free () with bad consequences.
 
S

s0suk3

You are quoting incorrectly what "restrict" means: The data pointed to
may be accessed through the restrict pointer itself, or through a
pointer derived from that pointer. If you have a pointer "int
*restrict p" and call free (p), then the argument to free is derived
from p and is allowed to access the data as much as it likes.

Wow, seems like everybody's got a different idea about the subject.
But Ben Bacarisse said it's legal to *access* the object through
another pointer or a variable that holds the object (or array element,
etc), but not to *modify* it. Is that what you meant to? Or is it also
illegal to merely access it (through something other than the
restricted pointer or something that's not derived from it)?
Now what is wrong is the following:

int* p = malloc (100);
int* restrict q = p;

p [0] = 1;
free (q);

(the call free (q) is just as wrong as an assignment q [0] = 2 or just
reading q [0] would be).

Reading q[0] is wrong? But q is the restricted pointer; why is it
wrong to access it or modify it?

Sebastian
 
S

santosh

You are quoting incorrectly what "restrict" means: The data pointed
to may be accessed through the restrict pointer itself, or through a
pointer derived from that pointer. If you have a pointer "int
*restrict p" and call free (p), then the argument to free is derived
from p and is allowed to access the data as much as it likes.

Wow, seems like everybody's got a different idea about the subject.
But Ben Bacarisse said it's legal to *access* the object through
another pointer or a variable that holds the object (or array element,
etc), but not to *modify* it. Is that what you meant to? Or is it also
illegal to merely access it (through something other than the
restricted pointer or something that's not derived from it)?
Now what is wrong is the following:

int* p = malloc (100);
int* restrict q = p;

p [0] = 1;
free (q);

(the call free (q) is just as wrong as an assignment q [0] = 2 or
just reading q [0] would be).

Reading q[0] is wrong? But q is the restricted pointer; why is it
wrong to access it or modify it?

Because you have lied to the compiler. The declaration of 'q' tells the
compiler that from this point forward, only 'q' or pointers derived
from it may be used to access the data, but the very next line you
violate this promise by indexing 'p'. Thus further behaviour is
undefined.
 
B

Ben Bacarisse

Wow, seems like everybody's got a different idea about the subject.
But Ben Bacarisse said it's legal to *access* the object through
another pointer or a variable that holds the object (or array element,
etc), but not to *modify* it.

It is complicated and I, as a non-expert, am wary of getting into too
much trouble by commenting on things I only partly understand, but it
seems to me that 6.7.3.1 (Formal definition of restrict) is careful to
talk about the exact objects that get accessed and how (to get the
value or to modify them).

For example, I think this is OK:

int A[2], *restrict p = A;
A[1] = 42;
p[0] = 43;

because no access that I can see violates the key para. 4. You can't
modify an object that you also access via a restrict-qualified
pointer:

int A[2], *restrict p = A;
A[1] = 42;
return p[1];

nor can you access the value of an object that has been changed though
one:

int A[2], *restrict p = A;
p[1] = 42;
return A[1];

All blanket statements about restrict pointers will be wrong unless
they paraphrase 6.7.3.1p4 so there is little to do other than read and
re-read it.
Is that what you meant to? Or is it also
illegal to merely access it (through something other than the
restricted pointer or something that's not derived from it)?

What matters is the "it". A restrict-qualified pointer to int that
points to the start of an array does mean the whole array is "off
limits" to all other accesses.
Now what is wrong is the following:

int* p = malloc (100);
int* restrict q = p;

p [0] = 1;
free (q);

(the call free (q) is just as wrong as an assignment q [0] = 2 or just
reading q [0] would be).

Reading q[0] is wrong?
But q is the restricted pointer; why is it
wrong to access it or modify it?

Because in this case the clause "Every other lvalue used to access the
value of X shall also have its address based on P" would be violated.
In particular, we would have an access based on q (q[0]), where the
value is modified (by p[0] = 1) and an lvalue (p[0]) whose address is
not based on q.

I won't post again until there is some more expert input. I fear I
may be in over my head.
 
A

Ajay

The "restrict" keyword allows to compiler to rearrange loads and
stores. So if you used int* instead of void* and an assignment to *rp
before the call to free (), the compiler could move the assignment
past the call to free () with bad consequences.

Two questions for clarification:

1. If we declare restricted pointer to an object, Is it true that,
essentially all the previously declared pointers cannot be used to
access the object until the restricted goes out of scope. And if we
do, the behavior is undefined

2. So in this case can I say. pointer 'space' is a not a pointer
derived from restricted pointer 'rp'.
And therefore cannot be used to access *rp. Hence cannot be used to
free it, free(space).

Thanks,
Ajay.
 
C

christian.bau

1. If we declare restricted pointer to an object, Is it true that,
essentially all the previously declared pointers cannot be used to
access the object until the restricted goes out of scope. And if we
do, the behavior is undefined

a.An object that is accessed through an lvalue derived from a restrict
pointer must not be modified through an lvalue that is _not_ derived
from the same restrict pointer.

b. An object that is accessed through an lvalue that is _not_ derived
from a restrict pointer must not be modified through an lvalue that
_is_ derived from that restrict pointer.

c. An object that is accessed through an lvalue that is derived from a
_const_ restrict pointer must not be modified at all.

As long is one object is only accessed and never modified at all
you're fine. An object can be accessed using any restrict pointers or
non-restrict pointer as much as you like. But if an object is modified
at all, then it must either be accessed and modified only using one
restrict pointer, or only using non-restrict pointers, but no mixture.
 
B

Ben Bacarisse

The point is that 'restrict' is not an inhibition to the compiler,
but a promise to it. It says that data accessible via that pointer
will only be accessed via that pointer.

That wording is likely to be misleading. It is about what is actually
accessed via that pointer not what is accessible via it. For example,
the rationale includes this example:

float * restrict a1, * restrict a2;
void init(int n)
{
float * t = malloc(2 * n * sizeof(float));
a1 = t; // a1 refers to 1st half
a2 = t + n; // a2 refers to 2nd half
}

The point being that the whole array is accessible via both a1 and a2
but the restrict qualification says that you won't make use of this
accessibility. No object accessed via a1 will be accessed via a2.
 

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
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top