赞
踩
VS集成开发环境上方有一个选项为Debug,表示这是代码的Debug版本,可以将其改为Release,表示这是代码的Release版本,那么Debug版本和Release版本有什么区别吗?
Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。
Release 称为发布版本,编译器对我们写的代码进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用,Release版本不能调试。
例:请看下面代码:
#include <stdio.h>
int main()
{
int i = 0;
int arr[10] = {0};
for(i=0; i<=12; i++)
{
arr[i] = 0;
printf("hehe\n");
}
return 0;
}
Debug版本下运行,该程序会出现死循环,即无限输出hehe,这是为什么呢?
i和arr都是局部变量,局部变量是存放在栈区上了,栈区内存的使用是先使用高地址处的空间,再使用低地址处的空间,数组随着下标的增长,地址由低到高变化,那么局部变量i和arr在栈区上的内存分配大致如下:
在vs2019环境下,变量i和arr相差两个整型,不同环境可能不一样,现在知道了局部变量i和arr的内存分配情况,我们先回归到代码。
由代码可知,从arr[10]开始越界访问,虽然对于程序而言arr[10]不存在,属于越界访问,但是对于实际内存而言,arr[10]就是arr[9]后面的一个位置,是真实存在的,因此可以将arr[10]赋值为0,同时也可以将arr[11]赋值为0,但是当访问到arr[12]的时候,由上面的内存分配图我们可以知道arr[12]实际上就是i,将arr[12]赋值为0,实际上就是将i赋值为0,因此i满足for循环条件,又会进入到下一轮循环,当i==12,再次访问到arr[12],将arr[12]赋值为0时,实际上又是将i赋值为0,又会进入下一轮的循环,因此这样下去就是无限死循环输出hehe。
那么在Release版本下,代码是怎么运行的呢?
如图所示在Release版本下,只输出了13次hehe,程序没有出现死循环,这是因为编译器对程序进行了优化:
由于Release版本无法进行调试,因此这里我们手动输出局部变量i和arr的地址:
前面说过局部变量存放在栈区,栈区的内存是从高地址向低地址使用的,因此变量i的地址应该大于arr的地址,可是由上图可知,变量i的地址小于arr的地址,这就是Release版本的优化,我们可以大致画出优化后的栈区内存分配图:
画出内存分配图后,我们可以更加清晰地了解到Releas版本对代码的优化,Release版本中,变量内存开辟的顺序发生了变化,先在高地址处开辟数组的空间,然后在低地址处开辟变量i的内存空间,这样即便数组越界访问,也不会影响到变量i的值,也就不会出现Debug版本死循环的情况。
由此可见Release版本的确会对代码进行优化,不过这种优化是底层的优化,比如这里对内存空间的开辟顺序进行了优化,而且这种优化并不会改变你的代码。
首先要注意的是,调试只有在Debug版本下才能进行:
F5:
F5向后执行代码,跳到下一个逻辑上的断点。
F9:
创建断点和取消断点。
断点的重要作用:可以在程序的任意位置设置断点。这样就可以使得程序运行到断点的位置停止执行,继而开始调试,一步步执行下去。
F9和F5是配合使用的。
F10:
逐过程,通常用来处理一个过程,一个过程可以是一次函数调用,或者是一条语句,逐过程执行会直接执行完整的过程,不会逐个执行过程中的每条语句。
F11
逐语句,就是每次都执行一条语句,这个快捷键可以使我们的执行逻辑进入函数内部(这是最长用的)。
CTRL + F5
开始执行不调试,如果你想让程序直接运行起来而不调试就可以直接使用。
监视窗口的打开过程如下:
打开监视窗口后,我们可以添加要监视的变量:
如图所示,我正在监视变量i和数组arr的信息:
打开内存窗口的过程如下:
打开内存窗口后,我们查看数组arr的内存信息:
如图所示,输入arr即数组首元素的地址,然后就可以在下面看到数组每个元素的地址以及每个元素在内存中被初始化为0。
打开调用堆栈窗口过程:
在main函数处设置断点后,然后使用F11逐语句执行,就会进入调用函数内部逐条执行语句,通过调用堆栈,可以清晰地反应函数的调用关系以及当前调用所处的位置。
在调试开始之后,有两种方式转到汇编:
(1)第一种方式:右击鼠标,选择【转到反汇编】:
(2)通过调试窗口选择反汇编:
可以查看当前运行环境的寄存器的使用信息。
优秀的代码:
常见的coding技巧:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。