This document http://pixelscommander.com/wp-content/uploads/2014/12/P10.pdf describes the 10 internal rules used by NASA/JPL laboratory to code safely in C. Very interesting.
Rule 9 says that :
Rule: The use of pointers should be restricted. Specifically, no more than one level of dereferencing is allowed. (...) Function pointers are not permitted. Rationale : Pointers are easily misused, even by experienced programmers. (...)
My questions are :
void*
, proliferating void*
unnecessarily throughout the code, not freeing data, double freeing data, freeing stack allocated data...how do you handle a 2 dimensional matrix of elements if only 1 level of derefercing is allowed ?
void foo( int (*matrix)[COLS], size_t rows ) // one level of dereference
{
...
matrix[i][j] = new_value();
}
int main( void )
{
int m[ROWS][COLS];
...
foo( m, ROWS );
}
if you write a generic algorithm (numerical integration, zero or minimum finding algorithm, etc), how do you use it if function pointers are not allowed ? Do you have to copy paste the code every time with a different function ?
NASA isn't using C for numerical work like that; there are far better tools available. But yes, you'd have to write non-generic code.
do you understand what "pointers are often misused" could refer to ?
One example of pointer misuse would be type punning; using a pointer to force a bit pattern to be interpreted as a different type:
double pi = 3.14159;
unsigned char *bytes = (unsigned char *) π
for ( int i = 0; i < sizeof pi; i++ )
printf( "%02x\n", bytes[i] );
The danger is if you decide to change the value stored in pi
by altering one of the values in bytes
:
bytes[1] = 0x00;
While useful in some cases, this kind of programming destroys the ability to validate code. Any tool that's looking for changes to pi
would most likely miss this.
NASA is most likely using C for low-level system controllers, avionics, and similar systems where complicated data structures and algorithms really aren't necessary, but where predictability and robust error handling are critical. Pointer operations open way too many "back doors" that can't easily be found and validated.
You kind of elided the important parts of that rationale:
Rationale: Pointers are easily misused, even by experienced programmers. They can make it hard to follow or analyze the flow of data in a program, especially by toolbased static analyzers. Function pointers, similarly, can seriously restrict the types of checks that can be performed by static analyzers and should only be used if there is a strong justification for their use, and ideally alternate means are provided to assist tool-based checkers determine flow of control and function call hierarchies. For instance, if function pointers are used, it can become impossible for a tool to prove absence of recursion, so alternate guarantees would have to be provided to make up for this loss in analytical capabilities.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With