I am writing a simple program which using getopt
function:
#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;
}
Executing it, outputs:
# ./test -f 1
Before getopt: optind is 1, address is 0x601040
After getopt: optind is 3, address is 0x601040
But when using gdb
to debug it, some weird things happen:
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
$1 = (int *) 0x7ffff7dd42a0 <optind>
(gdb) n
16 switch (c) {
(gdb) n
18 fname = optarg;
(gdb)
19 break;
(gdb) p &optind
$2 = (int *) 0x7ffff7dd42a0 <optind>
(gdb) p optind
$3 = 1
I can see using p optind
command, it outputs 1
(should be 3
), and this variable address is 0x7ffff7dd42a0
, not 0x601040
.
Using readelf
command:
# 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
It also display one optind
, and its address should be 0x601040
. So when using gdb
, why does it get optind
from 0x7ffff7dd42a0
? What is it?
Update:
Using the newest gdb 7.11
, and find this issue has been fixed.
This is an obscure gdb bug, triggered by another obscure feature known as a copy relocation.