关于内存的观察点写入本地静态?

时间:2014-01-22 16:47:57

标签: static gdb local-variables watchpoint

我想在静态本地s_db上设置观察点:

static sqlite3*& GetSqliteDb()
{
    static std::once_flag flag;
    static sqlite3* s_db = NULL;

    std::call_once(flag, []() {
        s_db = ...
        ...
    });
}

我尝试使用file::function::name设置观察点,但它给我带来了麻烦:

$ gdb
GNU gdb (GDB) 7.6.2
Copyright (C) 2013 Free Software Foundation, Inc.
...
(gdb) file ./bin/Debug/ac-test 
Reading symbols from ...
(gdb) watch ac-sqlite.cpp::GetSqliteDb::s_db
No symbol "ac" in current context.
(gdb) watch "ac-sqlite.cpp::GetSqliteDb::s_db"
Cannot watch constant value `"ac-sqlite.cpp::GetSqliteDb::s_db"'.
(gdb) watch GetSqliteDb()::s_db
A syntax error in expression, near `s_db'.
(gdb) watch GetSqliteDb::s_db
No symbol "s_db" in specified context.
(gdb) watch s_db
No symbol "s_db" in current context.
(gdb) 

为了完整性,我使用-O0 -g3构建,因此即使是符号常量名也可用。

如何在静态本地s_db上设置写入观察点?

2 个答案:

答案 0 :(得分:1)

似乎如果我设置一个带有错误的C ++名称的观察点,那么一切都很好。如果我使用解码的C ++名称设置一个观察点,那么gdb在函数中找不到静态可变量。这是我在Windows上使用gcc和gdb测试的一个示例:

void GetSqliteDb()
{
  static int *s_db = 0;
  s_db = new int;
  *s_db = 1;
  *s_db = 2;
   s_db = 0;
}

int main()
{
   GetSqliteDb();
   return 0;
}

这是nm输出:

>nm a.exe | grep s_db
00405020 b __ZZ11GetSqliteDbvE4s_db

>nm a.exe | grep s_db | c++filt
00405020 b GetSqliteDb()::s_db

这是一个gdb会话:

>gdb -q a.exe
Reading symbols from a.exe...done.
(gdb) watch GetSqliteDb::s_db
No symbol "s_db" in specified context.
(gdb) watch _ZZ11GetSqliteDbvE4s_db
Hardware watchpoint 1: _ZZ11GetSqliteDbvE4s_db
(gdb) start
Temporary breakpoint 2 at 0x4013cb: file main.cpp, line 11.
Starting program: a.exe
[New Thread 1688.0xff8]

(gdb) info watchpoints
Num     Type           Disp Enb Address    What
1       hw watchpoint  keep y              _ZZ11GetSqliteDbvE4s_db

Temporary breakpoint 2, main () at main.cpp:11
11      {
(gdb) c
Continuing.
Hardware watchpoint 1: _ZZ11GetSqliteDbvE4s_db

Old value = 0
New value = 4007328
GetSqliteDb () at main.cpp:5
5         *s_db = 1;
(gdb) c
Continuing.
Hardware watchpoint 1: _ZZ11GetSqliteDbvE4s_db

Old value = 4007328
New value = 0
GetSqliteDb () at main.cpp:8
8       }
(gdb) c
Continuing.
[Inferior 1 (process 1688) exited normally]

<强>更新

<小时/> 我使用gdb 7.6.2在RHEL 6.3(2.6.32-279.el6.x86_64)上测试了相同的示例,它正确设置了一个观察点。所以我无法在这个平台上重现这个问题:

>gdb a.out
GNU gdb (GDB) 7.6.2
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/a.out...done.
(gdb) watch GetSqliteDb::s_db
Hardware watchpoint 1: GetSqliteDb::s_db
(gdb) r
Starting program: /home/a.out
Hardware watchpoint 1: GetSqliteDb::s_db

Old value = (int *) 0x0
New value = (int *) 0x601010
GetSqliteDb () at main.cpp:5
5         *s_db = 1;
(gdb) c
Continuing.
Hardware watchpoint 1: GetSqliteDb::s_db

Old value = (int *) 0x601010
New value = (int *) 0x0
GetSqliteDb () at main.cpp:8
8       }
(gdb)

答案 1 :(得分:1)

您似乎需要使用s_db运算符取消引用*变量的地址。
请参阅文档中的Setting Watchpoints。这个观察点应该有效:

(gdb) watch *("ac-sqlite.cpp::GetSqliteDb::s_db")