a的作用是什么?
先引用一段维基百科上的介绍: 作用域(Scope)是一个程序设计术语,用于描述程序中变量、常数或函数的作用范围,以及这些对象所拥有的内存分配区间。C语言中没有提供对作用域的专门支持,因此需要编译器来完成从源代码到机器码的转换时自动添加。 作用域在函数式编程语言中最重要,几乎所有的函数式语言都通过实现一个抽象的“调用框架”(call frame)来保存局部变量的状态,而局部变量是按作用域组织起来的。这种机制使得大部分的语言都能很方便地支持递归,而不必担心堆栈能否容纳得下。而在非函数式的编程语言中,虽然作用域的概念依然存在,但已经不再是最重要的了。例如,在C和C++这样的语言中,只要正确配置编译器选项,就可以让编译器把局部变量存储在寄存器中而不是堆中,从而避免了因堆空间不足导致的崩溃。类似的,在Java中,本地方法(native method)能够使用JVMCI模拟C/C++的寄存器保存,以达到同样的目的。
再来看a的作用: a实际上是指向int型的指针,但它被当作参数传递给func1()的时候,它的作用域就在func1()内部了;当return之后,它又回到前面声明的地方继续存活(当然如果直接返回的话,就会报错,因为这样会破坏调用者所持有的a的副本)。换句话说,a在这个例子里面拥有两个不同的生命周期——一个是作为全局变量的时候,另一个是作为func1()参数的时候。由于不同生命周期使用的存储区域是不同的,所以这种情况并没有导致所谓“内存泄漏”的问题。
同样,在C或者C++里如果没有正确配置编译器,造成函数内局部变量占用外部的内存空间也不能算错,只不过性能会比较糟糕而已(因为每次函数的执行都要重新创建一整个函数栈,里面的局部变量都需要重新申请内存空间)。 以上都是未考虑运行时的结果。在考虑了运行时之后,所有那些所谓“本来应该失效”的操作都有可能实际仍然会有效。例如,对于函数式语言,每一个函数都有一个对应的数据流,而数据流中的每个元素都有一个类型标志,根据类型标志可以找到该元素的起源,也就是说可以追踪每一个操作对应的来源。因此在检测漏洞的时候,往往不需要判断是否存在内存泄漏,而是直接看是否有非法的操作,比如递归是否超过了限制等等。