肯定有什么事情搞砸了 gdb 逻辑。我在gcc 4.8.3 中遇到您描述的行为,在cygwin(32 位)中运行。
我在我的 gdb 会话中为您的代码获取此输出:
Breakpoint 1, main () at test.cpp:21
21 char** d = NULL;
(gdb) s
22 c(d);
(gdb) s
c (q=0x0) at test.cpp:9
9 q = new char*[2];
(gdb) s
13 if (q == NULL)
(gdb) p q
$1 = (char **) 0x0
(gdb) p &q
$2 = (char ***) 0x22abd0
(gdb) x 0x22abd0
0x22abd0: 0x00000000
现在,如果我像这样简单地更改您的功能:
void c (char** q)
{
cout << q << endl;
q = new char*[2];
if (q == NULL)
cout<<"NO OK";
else
cout<<"OK";
}
gdb 现在似乎能够获取该 q 参数的值:
Breakpoint 1, main () at test.cpp:21
21 char** d = NULL;
(gdb) s
22 c(d);
(gdb) s
c (q=0x0) at test.cpp:8
8 cout << q << endl;
(gdb) s
0
9 q = new char*[2];
(gdb) s
13 if (q == NULL)
(gdb) p q
$1 = (char **) 0x2004a0a8
(gdb) p &q
$2 = (char ***) 0x22abd0
(gdb) x 0x22abd0
0x22abd0: 0x2004a0a8
让我们像这样更改代码:
void c (char** q)
{
q = new char*[2];
cout << q << endl;
if (q == NULL)
cout<<"NO OK";
else
cout<<"OK";
}
此函数生成的代码如下所示:(compiled -g -ggdb -O0)
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $40, %esp
movl $8, (%esp)
call __Znaj
movl %eax, -12(%ebp)
movl -12(%ebp), %eax
movl %eax, 4(%esp)
movl $__ZSt4cout, (%esp)
call __ZNSolsEPKv
movl $__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)
movl %eax, (%esp)
call __ZNSolsEPFRSoS_E
cmpl $0, -12(%ebp)
jne L2
movl $LC0, 4(%esp)
movl $__ZSt4cout, (%esp)
call __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
jmp L1
现在从这段代码看来,编译器将if (q == NULL) 用于$ebp - 12 的值。让我们看看在gdb 会话期间这是如何进行的:
Breakpoint 1, main () at test.cpp:19
19 char** d = NULL;
(gdb) s
20 c(d);
(gdb) s
c (q=0x0) at test.cpp:8
8 q = new char*[2];
(gdb) s
9 cout << q << endl;
(gdb) s
0x2003a078
11 if (q == NULL)
(gdb) p q
$1 = (char **) 0x0
(gdb) p &q
$2 = (char ***) 0x22abd0
(gdb) p $ebp
$3 = (void *) 0x22abc8
(gdb) p $ebp - 12
$4 = (void *) 0x22abbc
(gdb) x 0x22abbc
0x22abbc: 0x2003a078
看起来gdb 在与实际地址不同的地址查找 q。您可能刚刚陷入了一个微妙的gcc - gdb 交互问题。