调试C程序时GDB断点触发异常:为何i值跳过3?
GDB调试中断点未按预期触发的原因分析
待调试的C程序
/* * Copyright (c) 2020, Dive into Systems, LLC (https://diveintosystems.org/) * Program with some bugs in the findAndReturnMax function */ #include <stdio.h> #include <stdlib.h> #include <string.h> /*************************************** * this function should find the largest element in the array and * "return" it through max * array: array of integer values * len: size of the array * max: set to the largest value in the array * returns: 0 on success and non-zero on an error */ int findAndReturnMax(int *array1, int len, int max) { int i; if (!array1 || (len <=0) ) { return -1; } max = array1[0]; for (i=1; i <= len; i++) { if (max < array1[i]) { max = array1[i]; } } return 0; } /***************************************/ int main(int argc, char *argv[]) { int arr[5] = { 17, 21, 44, 2, 60 }; int max = arr[0]; if ( findAndReturnMax(arr, 5, max) != 0 ) { printf("strange error\n"); exit(1); } printf("max value in the array is %d\n", max); return 0; }
GDB调试会话记录
tetyang@tet:~/clash/clash/learn_c$ gdb badprog (gdb) break 27 Breakpoint 1 at 0x11fc: file badprog.c, line 27. (gdb) run Starting program: /home/tetyang/clash/clash/learn_c/badprog [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Breakpoint 1, findAndReturnMax (array1=0x7fffffffdb30, len=5, max=17) at badprog.c:27 27 max = array1[i]; (gdb) print i $1 = 1 (gdb) cont Continuing. Breakpoint 1, findAndReturnMax (array1=0x7fffffffdb30, len=5, max=21) at badprog.c:27 27 max = array1[i]; (gdb) print i $2 = 2 (gdb) cont Continuing. Breakpoint 1, findAndReturnMax (array1=0x7fffffffdb30, len=5, max=44) at badprog.c:27 27 max = array1[i]; (gdb) print i $3 = 4 (gdb) cont Continuing. max value in the array is 17 [Inferior 1 (process 690122) exited normally] (gdb)
问题原因分析
你看到的不是“一次执行两次断点”,而是部分循环迭代没有执行到断点所在的代码行,具体原因如下:
- 断点位置的条件性执行:断点设在第27行
max = array1[i];,这行代码被包裹在if (max < array1[i])条件判断中。只有当当前数组元素array1[i]大于当前max值时,才会执行这行代码,触发断点:- 当
i=3时,数组元素是2,此时max的值是44,44 < 2不成立,不会进入if分支,因此不会触发断点。 - 当
i=4时,数组元素是60,44 < 60成立,执行第27行,触发断点。
- 当
- 循环边界的越界问题:for循环的条件是
i <= len,而数组arr的有效索引范围是0~4。当i=5时,访问array1[5]属于数组越界访问,内存值不确定。如果这个值不大于当前max(此时为60),同样不会执行第27行,因此也不会触发断点。
程序的其他关键bug
除了断点的误解,代码本身还有两个严重问题:
- 传值调用导致max无法更新:
findAndReturnMax函数的第三个参数是int max,属于传值调用,函数内部对max的修改不会影响main函数中的max变量,这就是最终输出max value in the array is 17的原因。需要将参数改为指针类型int *max,并通过指针修改值。 - 数组越界访问:循环条件
i <= len会导致访问超出数组有效索引范围的内存,可能引发未定义行为,应该改为i < len。
内容的提问来源于stack exchange,提问作者ll cool
相关产品推荐
相关产品推荐

