首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >gdb的奇怪行为

gdb的奇怪行为
EN

Stack Overflow用户
提问于 2014-07-07 16:36:09
回答 3查看 2.8K关注 0票数 3

我正在gdb中调试以下示例代码

代码语言:javascript
复制
#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的行为如下

代码语言:javascript
复制
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值为空,但代码的执行方式不同。

EN

回答 3

Stack Overflow用户

发布于 2014-07-07 16:38:48

好吧:warning: Source file is more recent than executable. --这可能就是你的答案。尝试重新编译您的代码。

票数 2
EN

Stack Overflow用户

发布于 2014-07-07 19:53:03

肯定有什么东西弄乱了gdb逻辑。我在cygwin (32位)中运行的gcc 4.8.3中遇到了您所描述的行为。

我将在我的gdb会话中为您的代码获取以下输出:

代码语言:javascript
复制
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

现在,如果我像这样简单地改变你的函数:

代码语言:javascript
复制
void c (char** q)
{
    cout << q << endl;
    q = new char*[2];
    if (q == NULL)
        cout<<"NO OK";
    else
        cout<<"OK";
}

gdb现在似乎能够获取q参数的值:

代码语言:javascript
复制
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

让我们像这样修改代码:

代码语言:javascript
复制
void c (char** q)
{
    q = new char*[2];
    cout << q << endl;
    if (q == NULL)
        cout<<"NO OK";
    else
        cout<<"OK";
}

此函数生成的代码如下所示:(compiled -g -ggdb -O0)

代码语言:javascript
复制
.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会话期间这是如何进行的:

代码语言:javascript
复制
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交互问题。

票数 0
EN

Stack Overflow用户

发布于 2014-07-07 21:13:30

通常,调试是在未优化的可执行文件上进行的(并测量优化后的可执行文件的性能)。这是因为快速地做事情和完全按照他们想要的方式做是相互排斥的。

您的c函数可以重写为

代码语言:javascript
复制
void c (char** q)
{
    cout<<"OK";
}

这是因为您在函数参数上分配了newed数组,即局部变量。这意味着代码对世界其他地方没有副作用。此外,new从不返回NULL,因此q == 0始终为false

编辑:好的,这实际上比简单的调试/发布差异复杂得多。由于实际问题在其他地方,为了使这个答案更有用,下面是它应该如何表现(代码用g++ 4.9.0编译,gdb版本是7.7)

未优化的g++ -g

代码语言:javascript
复制
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

代码语言:javascript
复制
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)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24606255

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档