我正在gdb中调试以下示例代码
#include <iostream>
#include <string.h>
using namespace std;
void c (char** q)
{
q = new char*[2];
if (q == NULL)
cout<<"NO OK";
else
cout<<"OK";
}
int main ()
{
char** d = NULL;
c(d);
return 1;
}现在这个程序给出的输出是"OK“,但是在gdb中调试这段代码时,我发现gdb -version GNU gdb (GDB) 7.5.1的行为如下
Breakpoint 1, c (q=0x0) at issue.cpp:8
warning: Source file is more recent than executable.
8 q = new char*[2];
(gdb) p q
$1 = (char **) 0x0
(gdb) n
9 if (q == NULL)
(gdb) p q
$2 = (char **) 0x0
(gdb) p q==0
$3 = true
(gdb) n
12 cout<<"OK";
(gdb) p q
$4 = (char **) 0x0
(gdb) p q==0
$5 = true
(gdb) gdb显示q值为空,但代码的执行方式不同。
发布于 2014-07-07 16:38:48
好吧:warning: Source file is more recent than executable. --这可能就是你的答案。尝试重新编译您的代码。
发布于 2014-07-07 19:53:03
肯定有什么东西弄乱了gdb逻辑。我在cygwin (32位)中运行的gcc 4.8.3中遇到了您所描述的行为。
我将在我的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现在,从这段代码可以看出,编译器将$ebp - 12处的值用于if (q == NULL)。让我们看看在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交互问题。
发布于 2014-07-07 21:13:30
通常,调试是在未优化的可执行文件上进行的(并测量优化后的可执行文件的性能)。这是因为快速地做事情和完全按照他们想要的方式做是相互排斥的。
您的c函数可以重写为
void c (char** q)
{
cout<<"OK";
}这是因为您在函数参数上分配了newed数组,即局部变量。这意味着代码对世界其他地方没有副作用。此外,new从不返回NULL,因此q == 0始终为false。
编辑:好的,这实际上比简单的调试/发布差异复杂得多。由于实际问题在其他地方,为了使这个答案更有用,下面是它应该如何表现(代码用g++ 4.9.0编译,gdb版本是7.7)
未优化的g++ -g
Breakpoint 1, c (q=0x0) at a.cpp:8
8 q = new char*[2];
(gdb) p q
$1 = (char **) 0x0
(gdb) n
9 if (q == NULL)
(gdb) p q
$2 = (char **) 0x611290
(gdb) p q==0
$3 = false
(gdb) n
12 cout<<"OK";
(gdb) p q
$4 = (char **) 0x611290
(gdb) p q==0
$5 = false优化的g++ -g -O2
Breakpoint 1, c (q=0x0) at a.cpp:8
8 q = new char*[2];
(gdb) p q
$1 = (char **) 0x0
(gdb) n
12 cout<<"OK";
(gdb) p q
$2 = <optimized out>
(gdb)https://stackoverflow.com/questions/24606255
复制相似问题