M
mathog
Ideally in any program the compiler should do as much of the heavy
lifting as possible. When it comes to pointers to memory though, the C
compiler is not much help. After:
int *ibuf;
ibuf = (int *)malloc(sizeof(int)*128);
a program could do lots things with ibuf that could lead to
invalid program operation and the compiler wouldn't give any help.
For instance, later in this same module:
somefunction(ibuf); /* may do a free(ibuf) */
*ibuf=1; /* if ibuf was released, this would be bad */
To avoid these issues I wonder how far one could get with one extra
keyword (here "primary") and a small number of additional compiler rules
and standard functions. The associated memory functions would be like:
void primary *pmalloc(); /* also pcalloc, prealloc */
void pfree(void primary **ptr); /* frees and sets pointer to NULL */
The first set would allocate memory and return this special type of
pointer to it, while pfree would release this memory. The idea being that:
int primary *ibuf = (int primary *)pmalloc(sizeof(int)*128);
int *ibuf2=ibuf; /* compiler OK, can make non primary copies */
...
free(ibuf); /* compiler error (cannot free(primary) ) */
pfree(&ibuf2); /* compiler error (cannot pfree(non primary)) */
...
*ibuf2=1; /* no problem */
...
pfree(&ibuf); /* compiler OK with this*/
...
*ibuf=1; /* compiler error (assignment to deallocated memory) */
*ibuf2=1; /* compiler error (assignment to deallocated memory) */
or change from pfree() on down to:
/* pass primary out. The function may deallocate it,
so primary memory is no longer valid here */
somefunction(ibuf);
...
*ibuf=1; /* compiler warning (assignment to iffy memory) */
*ibuf2=1; /* compiler error (assignment to iffy memory) */
or change from pfree() on down to:
return{ibuf); /* compiler is OK with returning a primary */
}
but
return(1); /* compiler warning (missing pfree(primary) ) */
}
Naturally this becomes complicated once structures are involved because
the two pointer types can become mixed. Not clear to me if the compiler
could keep up with the complications or not. If
"astruct" contains:
int primary *ibuf;
and in a function
astruct->ibuf = (int primary *)pmalloc(sizeof(int)*128);
int *ibuf2=ibuf;
...
somefunction(astruct); /* This could pfree astruct->ibuf */
*(astruct->ibuf)=1; // compiler warning (assignment to iffy memory)
*ibuf2=1; //compiler warning (assignment to iffy memory)
This is where things might fall apart. If calling a function with a
struct containing primary memory references marks them all as "iffy" it
is going to be pretty much impossible to leave the "iffy" warning
enabled. However, since the only way to free a primary is through
pfree(), and that always resets the pointer to NULL, one could have:
somefunction(astruct);
if(astruct->ibuf){ // post test compiler knows primary is OK
*(astruct->ibuf)=1; // compiler OK
*ibuf2=1; //compiler OK
}
Would the requirement that pfree() set the primary pointer to NULL be
sufficient for the compiler to be able to catch the "iffy" errors,
and disable those warnings subsequent to a test? It seems to me that
at least on extra rule would be needed:
int primary *ibuf = (int primary *)pmalloc(sizeof(int)*128);
int *ibuf2=ibuf; //no problem
int primary *ibufp=ibuf; //compiler error (duplicates primary)
to get around that the compiler would need some special function or
other method to handle this case:
/* returns the pointer to primary memory and sets src to NULL */
void primary *pxfer(void primary **src);
so that after
astruct->ibufp= (int primary *)pxfer(&ibuf);
the compiler knows that ibufp contains the original ptr from ibuf, that
ibuf has been set to NULL, and that secondary pointers for ibuf are now
secondary pointers for ibufp.
Regards,
David Mathog
lifting as possible. When it comes to pointers to memory though, the C
compiler is not much help. After:
int *ibuf;
ibuf = (int *)malloc(sizeof(int)*128);
a program could do lots things with ibuf that could lead to
invalid program operation and the compiler wouldn't give any help.
For instance, later in this same module:
somefunction(ibuf); /* may do a free(ibuf) */
*ibuf=1; /* if ibuf was released, this would be bad */
To avoid these issues I wonder how far one could get with one extra
keyword (here "primary") and a small number of additional compiler rules
and standard functions. The associated memory functions would be like:
void primary *pmalloc(); /* also pcalloc, prealloc */
void pfree(void primary **ptr); /* frees and sets pointer to NULL */
The first set would allocate memory and return this special type of
pointer to it, while pfree would release this memory. The idea being that:
int primary *ibuf = (int primary *)pmalloc(sizeof(int)*128);
int *ibuf2=ibuf; /* compiler OK, can make non primary copies */
...
free(ibuf); /* compiler error (cannot free(primary) ) */
pfree(&ibuf2); /* compiler error (cannot pfree(non primary)) */
...
*ibuf2=1; /* no problem */
...
pfree(&ibuf); /* compiler OK with this*/
...
*ibuf=1; /* compiler error (assignment to deallocated memory) */
*ibuf2=1; /* compiler error (assignment to deallocated memory) */
or change from pfree() on down to:
/* pass primary out. The function may deallocate it,
so primary memory is no longer valid here */
somefunction(ibuf);
...
*ibuf=1; /* compiler warning (assignment to iffy memory) */
*ibuf2=1; /* compiler error (assignment to iffy memory) */
or change from pfree() on down to:
return{ibuf); /* compiler is OK with returning a primary */
}
but
return(1); /* compiler warning (missing pfree(primary) ) */
}
Naturally this becomes complicated once structures are involved because
the two pointer types can become mixed. Not clear to me if the compiler
could keep up with the complications or not. If
"astruct" contains:
int primary *ibuf;
and in a function
astruct->ibuf = (int primary *)pmalloc(sizeof(int)*128);
int *ibuf2=ibuf;
...
somefunction(astruct); /* This could pfree astruct->ibuf */
*(astruct->ibuf)=1; // compiler warning (assignment to iffy memory)
*ibuf2=1; //compiler warning (assignment to iffy memory)
This is where things might fall apart. If calling a function with a
struct containing primary memory references marks them all as "iffy" it
is going to be pretty much impossible to leave the "iffy" warning
enabled. However, since the only way to free a primary is through
pfree(), and that always resets the pointer to NULL, one could have:
somefunction(astruct);
if(astruct->ibuf){ // post test compiler knows primary is OK
*(astruct->ibuf)=1; // compiler OK
*ibuf2=1; //compiler OK
}
Would the requirement that pfree() set the primary pointer to NULL be
sufficient for the compiler to be able to catch the "iffy" errors,
and disable those warnings subsequent to a test? It seems to me that
at least on extra rule would be needed:
int primary *ibuf = (int primary *)pmalloc(sizeof(int)*128);
int *ibuf2=ibuf; //no problem
int primary *ibufp=ibuf; //compiler error (duplicates primary)
to get around that the compiler would need some special function or
other method to handle this case:
/* returns the pointer to primary memory and sets src to NULL */
void primary *pxfer(void primary **src);
so that after
astruct->ibufp= (int primary *)pxfer(&ibuf);
the compiler knows that ibufp contains the original ptr from ibuf, that
ibuf has been set to NULL, and that secondary pointers for ibuf are now
secondary pointers for ibufp.
Regards,
David Mathog