Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Restricting pointer access to zero offset?

Reply
Thread Tools

Restricting pointer access to zero offset?

 
 
David Mathog
Guest
Posts: n/a
 
      03-14-2011
Normally in a case like this:

char *string=NULL;
....
string=malloc(ALLOCSIZE);

it is fine and proper to later access string with these
string[i]
string++

However, these are situations where one would like to forbid nonzero
offset access to a pointer. Is there a way to tell a compiler that
this should be an error? For instance, in a structure situation like
this:

typedef struct is_inner INNER;
typedef struct is_outer OUTER;
struct is_outer {
INNER *list;
int blah;
/*etc.*/
};
struct is_inner{
char *string;
int length;
}

OUTER *ohandle;
ohandle=malloc(sizeof(OUTER));
ohandle->list=malloc(sizeof(INNER)*N);

These operations:

ohandle++
ohandle[i]

are mistakes, at least in the intended use of this code, since ohandle
is a single struct. However, the compiler does not issue a warning
since they are valid pointer operations. Where they occur the
programmer probably meant

ohandle->list++;
ohandle->list[i];

Is there any standard way to tell a compiler that "accessing this
pointer with any nonzero offset is illegal?" This isn't static and it
isn't const. The closest words II can think of for the desired
behavior are "pinned" and "locked", but there are no such keywords.

I know the situation can be avoided by passing the structure and not a
pointer to the structure, but that isn't going to be good, performance
wise, when the structure in question is large and complex.

Thanks,

David Mathog

 
Reply With Quote
 
 
 
 
Ike Naar
Guest
Posts: n/a
 
      03-14-2011
On 2011-03-14, David Mathog <> wrote:
> Normally in a case like this:
>
> char *string=NULL;
> ...
> string=malloc(ALLOCSIZE);
>
> it is fine and proper to later access string with these
> string[i]
> string++
>
> However, these are situations where one would like to forbid nonzero
> offset access to a pointer. Is there a way to tell a compiler that
> this should be an error?


Would this be an option:

char * const string = malloc(ALLOCSIZE);
 
Reply With Quote
 
 
 
 
David Mathog
Guest
Posts: n/a
 
      03-14-2011
On Mar 14, 10:29*am, Ike Naar <i...@iceland.freeshell.org> wrote:
> On 2011-03-14, David Mathog <dmat...@gmail.com> wrote:
>
> > Normally in a case like this:

>
> > * char *string=NULL;
> > ...
> > * string=malloc(ALLOCSIZE);

>
> > it is fine and proper to later access string with these
> > * string[i]
> > * string++

>
> > However, these are situations where one would like to forbid nonzero
> > offset access to a pointer. Is there a way to tell a compiler that
> > this should be an error?

>
> Would this be an option:
>
> * * char * const string = malloc(ALLOCSIZE);


Unfortunately no, because that breaks normal structure usage like:

outer->blah=value;

which needs to still work. For the same reason an opaque type isn't
quite what I am after. The idea is to catch the use of a pointer to a
struct in an unintended manner, not to make it impossible to use the
pointer to a struct to access that pointers structure elements.

If outer is "const", then when gcc tries to compile that the line
above, it leads to this:

error: assignment of read-only location

Restating the goal another way:

1. dereference pointer to reach structure elements = OK
2. dereference pointer any other way = NOT OK
3. copy pointer = OK
4. free pointer = OK

I can see why this would be hard well into the compilation, at which
point 1 & 2 both look like ptr+offset, but earlier on the compiler
should, in theory, be able to make this distinction.

Thanks,

David Mathog





 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      03-14-2011
David Mathog <> writes:

> On Mar 14, 10:29Â*am, Ike Naar <i...@iceland.freeshell.org> wrote:
>> On 2011-03-14, David Mathog <dmat...@gmail.com> wrote:
>>
>> > Normally in a case like this:

>>
>> > Â* char *string=NULL;
>> > ...
>> > Â* string=malloc(ALLOCSIZE);

>>
>> > it is fine and proper to later access string with these
>> > Â* string[i]
>> > Â* string++

>>
>> > However, these are situations where one would like to forbid nonzero
>> > offset access to a pointer. Is there a way to tell a compiler that
>> > this should be an error?

>>
>> Would this be an option:
>>
>> Â* Â* char * const string = malloc(ALLOCSIZE);

>
> Unfortunately no, because that breaks normal structure usage like:
>
> outer->blah=value;
>
> which needs to still work.


No, you can assign to a member through a const pointer. It's only when
the pointer is to a const object that the assignment is a constraint
violation. I.e.

const struct S *outer;
/* or struct S const *outer; */

is not the same as

struct S *const outer;

> For the same reason an opaque type isn't
> quite what I am after. The idea is to catch the use of a pointer to a
> struct in an unintended manner, not to make it impossible to use the
> pointer to a struct to access that pointers structure elements.
>
> If outer is "const", then when gcc tries to compile that the line
> above, it leads to this:
>
> error: assignment of read-only location


I suspect you have a pointer to const rather than a const pointer.

> Restating the goal another way:
>
> 1. dereference pointer to reach structure elements = OK
> 2. dereference pointer any other way = NOT OK
> 3. copy pointer = OK
> 4. free pointer = OK
>
> I can see why this would be hard well into the compilation, at which
> point 1 & 2 both look like ptr+offset, but earlier on the compiler
> should, in theory, be able to make this distinction.


Many languages can do what you want, but I don't think it's possible in
C. Making the pointer const does rule out one of cases you wanted to
rule out (ptr++) but it has no effect on ptr[1].

--
Ben.
 
Reply With Quote
 
David Mathog
Guest
Posts: n/a
 
      03-17-2011
On thinking about this a little more I think the issue is that there
are pointer properties which have no corresponding keywords to control
them. Here is a list of pointer properties and associated control
options in C (probably incomplete, definitely not written by a
language specialist, so please forgive incorrect terminology). In
some instances there are keywords to control the property, in others,
not.

1. Pointer may be changed. Examples:

char *ptr;
ptr++;
ptr--;
ptr += offset;

Keyword "const" prevents these operations.

2. Pointer may be used to reference memory at an offset by
sizeof(type). Example:

int *var;
*(var + offset) = var[offset + 1];

No keyword prevents these actions. Stopping these actions comes up in
the context of "single vs. multiple". That is:

int *var;

may reference one int, or it may reference many, and there is
currently no way to tell the compiler which is desired. A keyword to
prevent this action: might be "single". As in:

int single *var;
...
/* compiler throws errors on the next two lines, which would
otherwise be legal */
foo = var[i];
foo = *(var + i);

3. Pointer is used to reference structure elements. Example:

var->element1;

Current keyword - none. Compilers throw errors if var is not a
pointer to a structure with a member named "element1". Additionally
there is opaque typing via typedef. A keyword to prevent this sort of
reference might be "opaque". Possibly useful in a situation where an
opaque type is used in the same file where the non-opaque definitions/
actions are coded. Otherwise, I cannot think of a situation where it
would be used.

4. memory allocation/free/reallocation via (void *).
Current keyword - const. But const doesn't really do much for the
situations where more than one pointer is used to reference an
allocated region, which can lead to "memory confusion". Example:

int *array=malloc(BIGNUMBER*sizeof(int));
int *oneptr;
int *twoptr;
oneptr=array;
twoptr=array;
...
/* far away in the code */
free(oneptr);
...
/* and later */
free(twoptr);

The first free() may or may not be an error, but the second one
certainly is. Const really doesn't get us out of this because we
might have assigned two pointers as in this case. A keyword "primary"
could clarify this situation (and should probably additionally have
the same effect as "const"), like:

int *array=NULL;
int primary *oneptr=NULL; /* an "official" memory reference */
int *twoptr=NULL;
array=malloc(BIGNUMBER*sizeof(int)); /* still works! */
oneptr=(int primary *)array; /* official reference filled */
/* forbidden: two primary pointers for the same memory
int primary *threeptr = oneptr;
*/
twoptr=array; /* no problem, neither is a primary */
...
/* far away in the code we run into this, which is fine,
because oneptr is a primary */
pfree(oneptr);
...
/* and later this, which is an error */
pfree(twoptr);

where

void pfree(void primary *address){}

similarly:

void primary *pmalloc(size);
/*etc.*/

Here adding the keyword would require new functions, because
currently
C treats all pointers as if they were "primary", and so free() etc.
cannot be easily modified in a backwards compatible manner to
implement this. Well, we could define "secondary", and have the
compiler flag calls to free() with secondary pointers, but "secondary"
would have to be applied to pretty much every pointer, which would be
awful. Primary, on the other hand, would affect fewer pointers.

5. reference at different scope, specifically, allowing a reference
outside of its defined scope. Example:

void function(int **var){
int localvar;
*var = &localvar;
}
...

int *var;
function(&var);
/* var points to nothing useful here, prepare to segfault */

Current keyword to control this - none. Current keyword to mediate
the effect (by changing the scope of the memory) is "static". A
keyword to disable this might be "local". Where

void function(int **var){
int localvar;
local int *ptr;
ptr=&localvar; /* this is OK, local references in scope */

function1(localvar); /* still good */

function2(ptr); /* <- here is where it gets complicated!!! */

/* compiler throws an error at the next line with something like:
"out of scope reference forbidden by local keyword"
*/
*var = &localvar;
}

and of course this would still be fine:

void function(int **var){
static int localvar;
*var = &localvar;
}

The logic cannot be inverted with "global" instead of "local", as it
won't be backwards compatible, because currently all pointers are
"global", and they would have to default to "local" for "global" to be
the keyword.

6. casting of pointers. Some of the situations above can reappear
when pointers are dereferenced. Example:

function(STRUCTDEF *holder){
}

STRUCTDEF **holder; /* an array of holder pointers */
...
/* in this instance, a pointer to a single STRUCTDEF, not
to an array of STRUCTDEFs */
function( &(holder[i]) );

this is back to the many vs. single issue from (2). So to fully
specify
what is intended this would become:

function(STRUCTDEF single *holder){
}

STRUCTDEF **holder; /* an array of holder pointers */
...
function( (STRUCTDEF single *)(&(holder[i]) );

which suggests that this type of keyword could be applied in the "more
restrictive" direction in casts, as is "const" now.

Regards,

David Mathog
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Can you set a class instance's attributes to zero by setting the instance to zero? Gerard Flanagan Python 3 11-19-2005 06:58 PM
home network but restricting childrens access to the web =?Utf-8?B?YW5keSBi?= Wireless Networking 4 07-26-2005 12:31 PM
Doubles and zero/negative zero Christopher Benson-Manica C Programming 4 07-01-2004 05:44 PM
memset all bits to zero will let float/double to zero? Zhiqiang Ye C Programming 53 06-28-2004 01:23 PM
Restricting User access to Router with TACACS Freeware Frank Beider Cisco 3 10-20-2003 04:39 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57