例如:
void func1(){
int i = 123;
func2(&i);
}
void func2(int *a){
*a = 456;
}
当func1
调用func2
时,指向局部变量的指针传递给func2
- 指针指向堆栈。这对C的规则是否安全?
感谢。
答案 0 :(得分:17)
i
的范围是func1
,它比func2
的呼叫更长。所以这是非常安全的。
答案 1 :(得分:4)
如前面的大多数答案中所述,在您的特殊情况下将指针传递给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;
}
在这种情况下,当DataBuff
中的指针用于将数据存储到EEPROM时,ASyncQueue.CommandArray[ASyncQueue.NextFreeEntry].BufferPtr
中的数据早已消失。
要修复此代码,至少需要声明static UINT8 DataBuff[25];
此外,还应该考虑声明static valueObj_t NVMemObj
,因为我们不知道被调用函数对该指针的作用。
简要说一下: 的 TL; DR 强>
即使它在C语言中是合法的,我认为在函数调用中传递指向自动变量的指针是有害的。你永远不会知道(并且通常你不想知道)被调用的函数对传递的值的作用。当被调用的函数建立别名时,你会遇到大麻烦。
只需2美分。
答案 2 :(得分:2)
是的,将指针传递给局部变量是安全的,但是你不能从函数返回指向自动局部变量的指针。
答案 3 :(得分:1)
是的,您的代码是安全的。
只要对象的生命周期没有结束,就像你一样传递局部变量是安全的。
答案 4 :(得分:1)
这对C的规则是否安全?
您正在做的事情是安全的,因为局部变量仍然有效且在范围内。访问其范围之外的本地变量是未定义的behvaior但这是完全没法的
答案 5 :(得分:1)
在您的情况下,您可以安全地使用&i
,直到i
有效。
现在,我们可以看到i
的有效期一直持续到func1()
。因为,func2()
正在调用func1()
而func1()
尚未完成执行,因此,i
仍然有效。
这就是为什么,通常将局部变量的地址传递给另一个函数通常允许(变量的生命周期未结束),但return
在return
之后,函数的局部变量不再存在)不允许。
TL; DR :您可以安全地使用&i
作为func2()
的参数,如此处所示。