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

例如:

void func1(){ int i = 123; func2(&i); } void func2(int *a){ *a = 456; } 

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

谢谢。

i的范围是func1 ,它比func2的调用func2 。 所以它非常安全。

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

然而,在现实世界的软件中,我认为这有害,因为你无法控制func2()对你的变量做什么。 func2()可以为其参数创建一个别名,以便在以后的某个时间异步使用它。 并且在那个时候,当稍后使用该别名时,局部变量int i可能会消失。

因此,从我的观点来看,将指针传递给本地(自动)变量是非常危险的,应该避免。

如果将func1()的变量声明为static int i;则可以这样做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; } 

在这种情况下,当ASyncQueue.CommandArray[ASyncQueue.NextFreeEntry].BufferPtr的指针用于将数据存储到EEPROM时, DataBuff的数据很久就消失了。

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

简而言之: TL; DR

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

只需2美分。

是的,将指针传递给局部变量是安全的,但是不能从函数返回指向自动局部变量的指针。

是的,您的代码是安全的。

只要对象的生命周期没有结束,就像你一样传递局部变量是安全的。

这对C的规则是否安全?

您正在做的是安全的,因为局部变量仍然有效且在范围内。 访问其范围之外的本地变量是未定义的behvaior但这完全没问题

在您的情况下,您可以安全地使用&i直到i有效。

现在,我们可以看到i的生命一直到func1()结束。 因为, func2()是从func1()调用的,而func1()还没有完成执行,因此, i仍然有效。

这就是为什么通常允许将局部变量的地址传递给另一个函数(变量的生命周期未结束),但是, return局部变量的地址(在return后立即return ,函数的局部变量不再存在)是不允许。

TL; DR :您可以安全地使用&i作为func2()的参数,如此处所示。