将指向本地变量的指针传递给函数:它安全吗?
例如:
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()
的参数,如此处所示。