为什么 gdb 会得到错误的 "optind" 变量值?
Why does gdb get wrong "optind" variable value?
我正在编写一个使用 getopt
函数的简单程序:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv)
{
char *fname;
int c;
printf("Before getopt: optind is %d, address is %p \n", optind, &optind);
while ((c = getopt(argc, argv, "f:")) != -1)
switch (c) {
case 'f':
fname = optarg;
break;
}
printf("After getopt: optind is %d, address is %p \n", optind, &optind);
return 0;
}
执行它,输出:
# ./test -f 1
Before getopt: optind is 1, address is 0x601040
After getopt: optind is 3, address is 0x601040
但是在使用gdb
调试的时候,出现了一些奇怪的事情:
13 printf("Before getopt: optind is %d, address is %p \n", optind, &optind);
(gdb) n
Before getopt: optind is 1, address is 0x601040
15 while ((c = getopt(argc, argv, "f:")) != -1)
(gdb) p &optind
= (int *) 0x7ffff7dd42a0 <optind>
(gdb) n
16 switch (c) {
(gdb) n
18 fname = optarg;
(gdb)
19 break;
(gdb) p &optind
= (int *) 0x7ffff7dd42a0 <optind>
(gdb) p optind
= 1
我可以看到使用p optind
命令,它输出1
(应该是3
),这个变量地址是0x7ffff7dd42a0
,而不是0x601040
.
使用readelf
命令:
# readelf -a test | grep optind
000000601040 000600000005 R_X86_64_COPY 0000000000601040 optind + 0
6: 0000000000601040 4 OBJECT GLOBAL DEFAULT 25 optind@GLIBC_2.2.5 (2)
54: 0000000000601040 4 OBJECT GLOBAL DEFAULT 25 optind@@GLIBC_2.2.5
它也显示一个optind
,它的地址应该是0x601040
。那么在使用gdb
时,为什么从0x7ffff7dd42a0
得到optind
呢?这是什么?
更新:
使用最新的 gdb 7.11
,发现此问题已得到修复。
这是一个 obscure gdb bug,由另一个称为复制重定位的模糊功能触发。
我正在编写一个使用 getopt
函数的简单程序:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv)
{
char *fname;
int c;
printf("Before getopt: optind is %d, address is %p \n", optind, &optind);
while ((c = getopt(argc, argv, "f:")) != -1)
switch (c) {
case 'f':
fname = optarg;
break;
}
printf("After getopt: optind is %d, address is %p \n", optind, &optind);
return 0;
}
执行它,输出:
# ./test -f 1
Before getopt: optind is 1, address is 0x601040
After getopt: optind is 3, address is 0x601040
但是在使用gdb
调试的时候,出现了一些奇怪的事情:
13 printf("Before getopt: optind is %d, address is %p \n", optind, &optind);
(gdb) n
Before getopt: optind is 1, address is 0x601040
15 while ((c = getopt(argc, argv, "f:")) != -1)
(gdb) p &optind
= (int *) 0x7ffff7dd42a0 <optind>
(gdb) n
16 switch (c) {
(gdb) n
18 fname = optarg;
(gdb)
19 break;
(gdb) p &optind
= (int *) 0x7ffff7dd42a0 <optind>
(gdb) p optind
= 1
我可以看到使用p optind
命令,它输出1
(应该是3
),这个变量地址是0x7ffff7dd42a0
,而不是0x601040
.
使用readelf
命令:
# readelf -a test | grep optind
000000601040 000600000005 R_X86_64_COPY 0000000000601040 optind + 0
6: 0000000000601040 4 OBJECT GLOBAL DEFAULT 25 optind@GLIBC_2.2.5 (2)
54: 0000000000601040 4 OBJECT GLOBAL DEFAULT 25 optind@@GLIBC_2.2.5
它也显示一个optind
,它的地址应该是0x601040
。那么在使用gdb
时,为什么从0x7ffff7dd42a0
得到optind
呢?这是什么?
更新:
使用最新的 gdb 7.11
,发现此问题已得到修复。
这是一个 obscure gdb bug,由另一个称为复制重定位的模糊功能触发。