C什么时候创建变量?
我使用的是ubuntu 12.04和Qt Creator 2.4.1。默认情况下,它构建我的C代码C什么时候创建变量?,c,debugging,variables,C,Debugging,Variables,我使用的是ubuntu 12.04和Qt Creator 2.4.1。默认情况下,它构建我的C代码GCC 我正在调试我的程序(Qt-Creator(使用GDB)),并且已经可以看到许多变量,这些变量将在程序的后续步骤中调用/创建。在程序开始时看到所有变量正常吗?换句话说,我是否因为调试选项(-g)而在程序的早期阶段看到变量?例如,我“步入”代码并在第一步停止,即int main() char[1000]mesg在第129行执行,但是,我已经可以看到它和它的内存地址了。或int tem\u ho
GCC
我正在调试我的程序(Qt-Creator(使用GDB)
),并且已经可以看到许多变量,这些变量将在程序的后续步骤中调用/创建。在程序开始时看到所有变量正常吗?换句话说,我是否因为调试选项(-g
)而在程序的早期阶段看到变量?例如,我“步入”代码并在第一步停止,即int main()
char[1000]mesg代码>在第129行执行,但是,我已经可以看到它和它的内存地址了。或int tem\u hopt\u dist=0代码>在第230行,但我已经看到它的值为“3” 是的,这是正常的。调试器不理解该语言的所有作用域语义,并显示数据,就好像所有变量都是在其最终内存位置初始化的,即使它们超出了作用域
有些调试器比其他调试器好。这是一个常见的恼怒源,例如,如果您习惯于将单独的索引变量都称为i
,而调试器不会区分它们。是的,这是正常的。调试器不理解该语言的所有作用域语义,并显示数据,就好像所有变量都是在其最终内存位置初始化的,即使它们超出了作用域
有些调试器比其他调试器好。这是一个常见的恼怒源,例如,如果您习惯于将单独的索引变量都称为i
,调试器不会区分它们。带有“静态持续时间”的变量(与static
关键字不同,尽管声明的变量static
通常具有静态持续时间)在执行模型中,在调用main
时,“创建”。具有“自动持续时间”的变量(“在堆栈上”,许多人都这么称呼它们)通过malloc
分配的变量持续到显式free
d(或通过realloc
等减少空间)
上面的密钥外带不是“在此时创建”,而是“在此点创建”。编译器可以自由地更早地这样做,如果这样做更有效的话。对于块范围、自动持续时间变量,通常将它们全部合并到一个大的入口点堆栈分配中最便宜,编译器只需一次“减法”即可完成指令(“从堆栈指针中减去常量”),在大多数典型的现代机器上。释放空间要么完全免费(“从函数返回”即可),要么只需一条指令(“将常量添加到堆栈指针”)
C99的可变长度数组(“VLA”)使这一点有点复杂。VLA通常必须在每次输入其封闭块时分配,并在每次退出块时释放。同样,这通常相当便宜(从堆栈指针中减去一个以创建VLA,再加一个以销毁它),但很明显,每个块两条指令比每个块零条指令更昂贵。这也会稍微影响一些编译时优化
如果您曾经使用过非标准的alloca
函数,这通常也是通过从堆栈指针进行减法来实现的,而且它可能不会很好地使用VLAs,因为这种减法倾向于假设编译器已经完成了自己的“从堆栈指针进行减法”恰好一次,就在函数本身开始之前。具有“静态持续时间”的变量(与static
关键字不同,尽管声明的static
变量通常具有静态持续时间)在执行模型中由调用main
的时间“创建”。具有“自动持续时间”(“许多人称之为堆栈上的持续时间”)是在输入其作用域时创建的。通过malloc
分配的变量持续到显式free
d(或通过realloc
等减少空间)
上面的密钥外带不是“此时创建”,而是“此时创建”。编译器可以自由地更早地执行此操作,如果这更有效的话。对于块范围、自动持续时间变量,通常最便宜的方法是将它们全部合并到一个大的入口点堆栈分配中,编译器只需一次“减法”即可指令(“从堆栈指针中减去常数”),在大多数典型的现代机器上。释放空间要么是完全免费的(“从函数返回”即可),要么只需要一条指令(“将常数添加到堆栈指针”)
C99的可变长度数组(“VLA”)使这一点有点复杂。VLA通常必须在每次输入其封闭块时分配,并在每次退出块时释放。同样,这通常相当便宜(从堆栈指针中减去一个以创建VLA,再加一个以销毁它),但很明显,每个块两条指令比每个块零条指令更昂贵。这也会稍微影响一些编译时优化
如果您曾经使用过非标准的alloca
函数,这通常也是通过从堆栈指针进行减法来实现的,而且它可能不会很好地使用VLAs,因为这种减法倾向于假设编译器已经完成了自己的“从堆栈指针进行减法”恰好一次,就在函数本身启动之前。很多次,静态定义的变量被编译到数据“部分”因此,如果您在该例程/函数的范围内,那么它可能在该点可见。数据段中的任何静态内容都可以在该例程的入口分配。很多时候,静态定义的变量被编译到程序的数据“段”,因此如果您在该例程/f的范围内