NASA C编码规则:误用指针

Ist*_*oki 4 c pointers

本文档http://pixelscommander.com/wp-content/uploads/2014/12/P10.pdf描述了NASA/JPL实验室用于在C中安全编码的10条内部规则.非常有趣.

规则9说:

规则:应限制指针的使用.具体而言,允许不超过一级解除引用.(...)不允许使用函数指针.理由:指针很容易被误用,即使是经验丰富的程序员也是如此.(......)

我的问题是:

  1. 如果只允许1级derefercing,你如何处理元素的二维矩阵?
  2. 如果你编写一个通用算法(数值积分,零或最小查找算法等),如果不允许函数指针,你如何使用它?您是否必须每次使用不同的功能复制粘贴代码?
  3. 你明白"指针经常被滥用"可能指的是什么?

Ide*_*Hat 6

  1. 手工编制索引.对于mxn矩阵,对于点i,j,索引是[i + j*n].不适用于锯齿状阵列.
  2. 是的,或使用宏疯狂.
  3. 违反严格的别名,访问未初始化的数据,访问释放的数据,访问越界数据,错误地指向指针指向的内容,将指针错误地转换为整数,将函数指针转换为a void*,void*在整个代码中不必要地扩散,而不是释放数据,双重释放数据,释放堆栈分配的数据......

  • 让我补充一点,C可以处理真正的多维数组,因为C99.您可以将它们声明为堆栈变量,使用单个`malloc()`调用和正确的指针类型轻松地动态分配它们,并且可以轻松地将它们传递给函数.所以,你不会被抛回到手工编制索引. (2认同)

Joh*_*ode 6

如果只允许1级derefercing,你如何处理元素的二维矩阵?

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 );
}
Run Code Online (Sandbox Code Playgroud)

如果你编写一个通用算法(数值积分,零或最小查找算法等),如果不允许函数指针,你如何使用它?您是否必须每次使用不同的功能复制粘贴代码?

NASA 并没有像这样使用C进行数值工作; 有提供更好的工具.但是,是的,你必须编写非通用代码.

你明白"指针经常被滥用"可能指的是什么?

指针误用的一个例子是类型惩罚 ; 使用指针强制将位模式解释为不同的类型:

double pi = 3.14159;
unsigned char *bytes = (unsigned char *) π
for ( int i = 0; i < sizeof pi; i++ )
  printf( "%02x\n", bytes[i] );
Run Code Online (Sandbox Code Playgroud)

如果您决定通过更改以下值中pi的一个值来更改存储的值,则存在危险bytes:

bytes[1] = 0x00;
Run Code Online (Sandbox Code Playgroud)

虽然在某些情况下很有用,但这种编程破坏了验证代码的能力.任何正在寻找变化的工具都很pi可能会错过这个.

NASA最有可能将C用于低级系统控制器,航空电子设备和类似系统,其中复杂的数据结构和算法确实不是必需的,但可预测性和强大的错误处理至关重要.指针操作打开太多"后门",无法轻易找到和验证.

你有点忽略了这个理由的重要部分:

理由:指针很容易被误用,即使是经验丰富的程序员也是如此.它们 使得很难跟踪或分析程序中的数据流,特别是通过基于工具的静态分析器.类似地,函数指针可以严重限制静态分析器可以执行的检查类型,并且只应在有充分理由使用的情况下使用,并且理想情况下提供备用方法以帮助基于工具的检查器确定控制流程和函数调用层次结构.例如,如果使用函数指针,工具就不可能证明没有递归,因此必须提供备用保证来弥补分析能力的这种损失.