为什么 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,由另一个称为复制重定位的模糊功能触发。