我目前正在尝试调试一个小型C程序,其总体结构如下所示:
int some_function(...) {
...
size_t buf_len = some_other_function(...)
...
}
main() {
...
int foo = some_function(...)
...
}
我在some_function()
设置断点(使用lldb)。但是,如果我在此断点处检查堆栈帧,它会显示已存在于本地范围内的变量buf_len
,甚至具有任意(?)值。如果在此函数之前未在任何地方声明变量,这怎么可能?
答案 0 :(得分:10)
根据§6.2.4/6 of the C11 Draft Standard:
对于没有可变长度数组类型的对象, 它的生命周期从进入到它所在的区块延伸 关联,直到该块的执行以任何方式结束。
因此,当执行进入buf_len
时,some_function()
在调试器中可见是不足为奇的。
答案 1 :(得分:5)
在编译期间,每个变量都会添加到符号表中。 因此,对变量的任何引用只有在已经声明并且插入到符号表中时才会解析。如果在声明之前引用变量,则会收到未定义引用的错误。
但是在函数序言期间,所有自动变量的空间在堆栈中被分配 all-in-one (即在IA32-64架构中,获得所有自动变量所需的空间减去堆栈帧中的堆栈指针寄存器的空间)。所需空间由编译器通过对该函数的符号表中存在的所有自动变量所需的存储空间求和来计算。
实际上,当在函数入口上创建堆栈帧时,所有自动变量都存在,即使在之后使用。
在某些情况下,变量未分配如果编译器优化它们,编译器优化代码选择不同的方式使用变量抑制它(即使用寄存器或简化流程和删除中间存储)。
答案 2 :(得分:2)
堆栈帧包含传入的args以及局部变量和其他一些东西。查看this,尤其是“结构”部分。断点不能让你在两个函数之间停止。在函数调用中,堆栈帧是最先创建的东西之一。