- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我们有一个非常大的项目。(大约 200'000 个文件)
当项目退出时,它在全局变量的解构中崩溃。
但是我们找不到变量定义的地方。
有人知道如何找到全局变量在哪里吗?
最佳答案
But we can't find where the variable defined.
大概,您想找出哪个全局变量导致了问题。如果你知道它是哪一个,你可以使用 grep
, 或 GDB info variable foobar
找到它。
让我们考虑一个例子。
cat foo.cc
#include <stdio.h>
#include <string>
using std::string;
string foo("foo");
string bar("bar");
string baz("baz");
// It is not valid to call this function with a global string.
void invalid_with_global(string *str)
{
printf("str: %s @%p)\n", str->c_str(), str);
printf("before dtor\n");
str->~string();
printf("after dtor\n");
}
int main()
{
invalid_with_global(&baz);
}
g++ -g foo.cc && gdb -q ./a.out
Reading symbols from /tmp/a.out...done.
(gdb) r
Starting program: /tmp/a.out
str: baz @0x601088)
before dtor
after dtor
*** glibc detected *** /tmp/a.out: double free or corruption (fasttop): 0x0000000000602070 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7ffff7583b96]
/usr/lib/x86_64-linux-gnu/libstdc++.so.6(_ZNSsD1Ev+0x23)[0x7ffff7b78c13]
/lib/x86_64-linux-gnu/libc.so.6(+0x3b901)[0x7ffff7540901]
/lib/x86_64-linux-gnu/libc.so.6(+0x3b985)[0x7ffff7540985]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf4)[0x7ffff7526774]
/tmp/a.out[0x4007f9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 ca:01 147024 /tmp/a.out
00600000-00601000 r--p 00000000 ca:01 147024 /tmp/a.out
00601000-00602000 rw-p 00001000 ca:01 147024 /tmp/a.out
00602000-00623000 rw-p 00000000 00:00 0 [heap]
7ffff7209000-7ffff7304000 r-xp 00000000 ca:01 881564 /lib/x86_64-linux-gnu/libm-2.15.so
7ffff7304000-7ffff7503000 ---p 000fb000 ca:01 881564 /lib/x86_64-linux-gnu/libm-2.15.so
7ffff7503000-7ffff7504000 r--p 000fa000 ca:01 881564 /lib/x86_64-linux-gnu/libm-2.15.so
7ffff7504000-7ffff7505000 rw-p 000fb000 ca:01 881564 /lib/x86_64-linux-gnu/libm-2.15.so
7ffff7505000-7ffff76ba000 r-xp 00000000 ca:01 881572 /lib/x86_64-linux-gnu/libc-2.15.so
7ffff76ba000-7ffff78b9000 ---p 001b5000 ca:01 881572 /lib/x86_64-linux-gnu/libc-2.15.so
7ffff78b9000-7ffff78bd000 r--p 001b4000 ca:01 881572 /lib/x86_64-linux-gnu/libc-2.15.so
7ffff78bd000-7ffff78bf000 rw-p 001b8000 ca:01 881572 /lib/x86_64-linux-gnu/libc-2.15.so
7ffff78bf000-7ffff78c4000 rw-p 00000000 00:00 0
7ffff78c4000-7ffff78d9000 r-xp 00000000 ca:01 881501 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff78d9000-7ffff7ad8000 ---p 00015000 ca:01 881501 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff7ad8000-7ffff7ad9000 r--p 00014000 ca:01 881501 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff7ad9000-7ffff7ada000 rw-p 00015000 ca:01 881501 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff7ada000-7ffff7bbc000 r-xp 00000000 ca:01 1096828 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7ffff7bbc000-7ffff7dbb000 ---p 000e2000 ca:01 1096828 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7ffff7dbb000-7ffff7dc3000 r--p 000e1000 ca:01 1096828 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7ffff7dc3000-7ffff7dc5000 rw-p 000e9000 ca:01 1096828 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7ffff7dc5000-7ffff7dda000 rw-p 00000000 00:00 0
7ffff7dda000-7ffff7dfc000 r-xp 00000000 ca:01 881673 /lib/x86_64-linux-gnu/ld-2.15.so
7ffff7fd8000-7ffff7fdd000 rw-p 00000000 00:00 0
7ffff7ff7000-7ffff7ffb000 rw-p 00000000 00:00 0
7ffff7ffb000-7ffff7ffc000 r-xp 00000000 00:00 0 [vdso]
7ffff7ffc000-7ffff7ffd000 r--p 00022000 ca:01 881673 /lib/x86_64-linux-gnu/ld-2.15.so
7ffff7ffd000-7ffff7fff000 rw-p 00023000 ca:01 881673 /lib/x86_64-linux-gnu/ld-2.15.so
7ffffffdd000-7ffffffff000 rw-p 00000000 00:00 0 [stack]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Program received signal SIGABRT, Aborted.
0x00007ffff753b425 in __GI_raise (sig=<optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
64 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 0x00007ffff753b425 in __GI_raise (sig=<optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1 0x00007ffff753eb8b in __GI_abort () at abort.c:91
#2 0x00007ffff757939e in __libc_message (do_abort=2, fmt=0x7ffff7683008 "*** glibc detected *** %s: %s: 0x%s ***\n") at ../sysdeps/unix/sysv/linux/libc_fatal.c:201
#3 0x00007ffff7583b96 in malloc_printerr (action=3, str=0x7ffff76831f8 "double free or corruption (fasttop)", ptr=<optimized out>) at malloc.c:5007
#4 0x00007ffff7b78c13 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007ffff7540901 in __run_exit_handlers (status=0, listp=0x7ffff78bd688 <__exit_funcs>, run_list_atexit=true) at exit.c:78
#6 0x00007ffff7540985 in __GI_exit (status=<optimized out>) at exit.c:100
#7 0x00007ffff7526774 in __libc_start_main (main=0x400904 <main()>, argc=1, ubp_av=0x7fffffffd828, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffd818) at libc-start.c:258
#8 0x00000000004007f9 in _start ()
此时,您知道您的全局“std::basic_string<...>”对象之一造成了麻烦,但您不知道是哪一个。
很容易发现:只需转到第 4 帧并打印 this
,对吧?
(gdb) fr 4
#4 0x00007ffff7b78c13 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
(gdb) p this
No symbol "this" in current context.
嗯,效果不是很好,因为我没有 libstdc++.so.6
的调试符号安装(如果给您带来麻烦的对象是在您自己的源代码中定义的,那么您不应该有那个麻烦)。
现在,我可以为我的 libstdc++.so.6
安装调试符号。 ,或者我可以使用我对 ABI 的了解。在 Linux/x86_64 上,第一个 ( this
) 参数在寄存器 %rdi
中传递.我无法使用当前的 %rdi
不过,因为它已经被用于其他用途。所以我在问题析构函数上设置了一个断点:std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()
, 然后重启。
在实际程序中,析构函数会被调用很多次,但我只对来自 exit
的调用感兴趣.所以我在 exit
上设置了断点,并且仅当遇到该断点时,我才会在析构函数上设置一个新断点。
(gdb) b exit
(gdb) r
Starting program: /tmp/a.out
str: baz @0x601088)
before dtor
after dtor
Breakpoint 1, __GI_exit (status=0) at exit.c:100
100 exit.c: No such file or directory.
(gdb) b std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()
Breakpoint 2 at 0x7ffff7b78bf0
(gdb) c
Continuing.
Breakpoint 2, 0x00007ffff7b78bf0 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
(gdb) bt
#0 0x00007ffff7b78bf0 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1 0x00007ffff7540901 in __run_exit_handlers (status=0, listp=0x7ffff78bd688 <__exit_funcs>, run_list_atexit=true) at exit.c:78
#2 0x00007ffff7540985 in __GI_exit (status=<optimized out>) at exit.c:100
#3 0x00007ffff7526774 in __libc_start_main (main=0x400904 <main()>, argc=1, ubp_av=0x7fffffffd828, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffd818) at libc-start.c:258
#4 0x00000000004007f9 in _start ()
(gdb) p/x $rdi
$1 = 0x601088
(gdb) c
Continuing.
*** glibc detected *** /tmp/a.out: double free or corruption (fasttop): 0x0000000000602070 ***
... as before, omitted ...
Program received signal SIGABRT, Aborted.
0x00007ffff753b425 in __GI_raise (sig=<optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
64 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
现在我们有了全局“坏”的地址:0x601088
,您会注意到它与我打印的值匹配。
最后我们准备好回答“它是哪个变量?”问题:
(gdb) info sym 0x601088
baz in section .bss of /tmp/a.out
瞧:问题变量是 baz
.最后:
(gdb) info var baz
All variables matching regular expression "baz":
File foo.cc:
std::string baz;
关于c++ - 如何使用 gdb 找到全局变量的析构函数调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15727823/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!