一次手误引出的bug

  在工做中写了这样一段代码:函数

 1 struct xx_param {
 2        int index1;
 3        int index2;
 4 };
 5 
 6 //func1, func2, func3为三个函数指针
 7 
 8 int init(a_func_t *func1, b_func_t *func2, c_func_t *func3, void *param)
 9 {
10        struct xx_param *p = (struct xx_param *)param;
11         func1(p->index1, p->index2);
12 }
13 
14 int prepare_init(int xx_index_1, int xx_index_2)
15 {
16         int err;
17         struct xx_param        xx;
18         
19        ......
20 
21         xx.index1 = xx_index1;
22         xx.index2 = xx_index2;
23 
24         if(init(func1, func2, func3, &xx_index1))
25                err = -xxx;
26 20        ......
27 
28         return err;
29 }

  很明显这个错误很普通,就是第24行应该为&xx,可是我手误错写成了&xx_index1。可是编译器不会报警,下面来讲一下这个错误的神奇之处,在Debug下永远是正确的,可是Release下永远跑飞。下面来分析一下为何:布局

  在Debug模式下参数是由栈来传递的,那么参数xx_index_1, xx_index_2在栈中的布局 与 xx结构体变量在栈中的布局彻底同样,所以虽然我取错了地址,可是根据&xx_index_1处获得的地址来获到xx_index1, xx_index_2,其实至关于将结构体变量xx赋值而后从&xx地址处取xx.index1,xx.index2变量(貌似还少了几回内存拷贝,虽然他是一个bug, ^_&),所以在Debug模式下这断代码永远是正确的。优化

  可是在Release下却不正确,由于在VS下,O2的优化级别下xx_index_1, xx_index_2是由寄存器ecx, edx来传递的,xx_index_1, xx_index_2两个变量的值不会所有在栈中分配(因为对xx_index1进行取地址,所以会致使编译器为xx_index1分配内存,可是xx_index_2确不会分配内存),这样从&xx地址去取数据时xx.index2变量取到的数据老是垃圾数据,所以软件在Release下老是挂掉,但若是将优化关掉却又能良好运行。
spa

  这个Bug很简单,可是现象却很诡异,所以感受值得一记。指针

相关文章
相关标签/搜索