将指向本地变量的指针传递给函数:它安全吗?

Alb*_*ang 16 c stack pointers

例如:

void func1(){
    int i = 123;
    func2(&i);
}
void func2(int *a){
    *a = 456;
}
Run Code Online (Sandbox Code Playgroud)

func1调用func2,一个指向局部变量传递到func2-指针指向堆栈.这对C的规则是否安全?

谢谢.

jua*_*nza 19

范围ifunc1和它的呼吁超过了func2.所以它非常安全.


opt*_*t12 5

如之前大多数答案中所述,func2()在特殊情况下将指针传递到是绝对安全的。

但是,在实际的软件中,我认为这很有害,因为您无法控制func2()变量的操作。func2()可以为其参数创建别名,以在以后的某个时间点异步使用它。并且那时,int i稍后使用此别名时,局部变量可能会消失。

因此,从我的角度来看,将指针传递给局部(自动)变量是极其危险的,应避免使用。

你可以这样做,如果你在声明变量func1()作为static int i;

在这种情况下,可以确保i不会回收和覆盖用于的内存。但是,您将需要设置一些Mutex锁定,以便在并发环境中对此存储器进行访问控制。

为了说明这个问题,下面是我昨天在为客户进行软件测试时偶然发现的一些代码。是的,它崩溃了...

void func1()
{
  // Data structure for NVMemory calls
  valueObj_t NVMemObj;

  // a data buffer for eeprom write
  UINT8 DataBuff[25];
  // [..]
  /* Assign the data pointer to NV Memory object */
  NVMemObj.record = &DataBuff[0];
  // [..]
  // Write parameter to EEPROM.
  (void)SetObject_ASync(para1, para2, para3, &NVMemObj);
  return;
}

void SetObject_ASync(para1, para2, para3, valueObj_t *MemoryRef)
{
  //[..]
  ASyncQueue.CommandArray[ASyncQueue.NextFreeEntry].BufferPtr  = MemoryRef->record;
  //[..]
  return;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,DataBuff当使用指针输入ASyncQueue.CommandArray[ASyncQueue.NextFreeEntry].BufferPtr将数据存储到EEPROM 时,数据中的数据将消失。

要修复此代码,至少需要声明static UINT8 DataBuff[25];另外,还应考虑也声明,static valueObj_t NVMemObj因为我们不知道被调用函数对该指针的作用。

简而言之: TL; DR

即使在C语言中是合法的,我也认为在函数调用中将指针传递给自动变量是有害的。您永远不会(通常也不想)知道被调用函数对传递的值到底做了什么。当被调用函数建立别名时,您会遇到麻烦。

只是我的2美分。

  • “ func2()可以为其参数创建一个别名,以便在以后的时间点异步使用它”。对于传递给函数的已分配内存,也可以这样说...它可能会为其创建别名,在调用者稍后释放内存后,它将尝试访问该别名。这里的重点不是调用者做错了什么,而是*被调用的函数*保持对自身的args的引用(在全局中的何处?),以便在*以后的调用*中重复使用。还要考虑到这是一个更安全的起点,因为它们不需要释放。TLDR;自动变量=好。保留指向其args = bad的指针的函数。 (4认同)