#include <iostream>
void do_something(void) {
std::cout << "blah blah" << std::endl;
auto lambda_func = [](void){
std::cout << "in lambda" << std::endl;
return;
};
lambda_func();
std::cout << "..." << std::endl;
return;
}
int main(int argc, char **argv) {
do_something();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在这个示例程序中,如果你编译(g++ gdb-call-lambda.cpp --std=c++11 -g)然后在gdb(gdb ./a.out)中运行它,你可以让GDB调用任何"普通"函数.例:
(gdb) break main
Breakpoint 1 at 0x4008e7: file gdb-call-lambda.cpp, line 20.
(gdb) r
Starting program: /home/keithb/dev/mytest/gdb-call-lambda/a.out
Breakpoint 1, main (argc=1, argv=0x7fffffffdfb8) at gdb-call-lambda.cpp:20
20 do_something();
(gdb) call do_something()
blah blah
in lambda
...
Run Code Online (Sandbox Code Playgroud)
但是,如果你然后尝试调用lambda:
(gdb) break do_something
Breakpoint 2 at 0x400891: file gdb-call-lambda.cpp, line 5.
(gdb) c
Continuing.
Breakpoint 2, do_something () at gdb-call-lambda.cpp:5
5 std::cout << "blah blah" << std::endl;
(gdb) n
blah blah
12 lambda_func();
(gdb) n
in lambda
14 std::cout << "..." << std::endl;
(gdb) call lambda_func()
Invalid data type for function to be called
Run Code Online (Sandbox Code Playgroud)
GDB有点吓坏了.所以我的问题是:你如何在GDB中调用lambda?询问GDB与正常函数相比,它所期望的东西没有任何兴趣:
(gdb) whatis lambda_func
type = __lambda0
(gdb) whatis do_something
type = void (void)
Run Code Online (Sandbox Code Playgroud)
我去看看lambda_func是否有任何特殊成员,例如一个调用的函数指针,类似于std :: function和/或std :: bind:
(gdb) print lambda_func
$1 = {<No data fields>}
Run Code Online (Sandbox Code Playgroud)
没有特别会员?好吧也许它只是一个美化的函数指针?
(gdb) call ((void (void)) lambda_func)()
Program received signal SIGSEGV, Segmentation fault.
0x00007fffffffdeaf in ?? ()
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on".
Evaluation of the expression containing the function
(at 0x0x7fffffffdeaf) will be abandoned.
When the function is done executing, GDB will silently stop.
Run Code Online (Sandbox Code Playgroud)
所以我甚至不能100%确定传递任何参数或特别是捕获类型的命令.
我试过此外call lambda_func.operator()(),call lambda_func::operator(),call lambda_func::operator()(),call __lambda0,call __lambda0(),call __lambda0::operator(),call __lambda0::operator()(),都无济于事.
谷歌搜索揭示了在lambdas中设置断点的事情,但没有关于如何从调试器中调用这些lambda的事情.
对于它的价值,这是使用g ++ 4.8.2-19ubuntu1和gdb 7.7-0ubuntu3.1在Ubuntu 14.04 64位上
我期待着call __lambdaX::operator()()作品,但事实并非如此.我认为这与GCC的实施有关.我不确定是否有更好的方法,但这是我的解决方案,当我需要在GDB中调用lambda时.
简而言之,GDB具有disassemble命令,它__lambda0::operator()() const在call指令行提供调试信息.然后,将该地址转换为函数指针并调用它.
示例解释得更好.
$ g++ -g -std=c++0x lambda.cpp
$ ./a.out
blah blah
in lambda
...
Run Code Online (Sandbox Code Playgroud)
GDB:
$ gdb ./a.out
GNU gdb (GDB) Fedora 7.7.1-13.fc20
Copyright (C) 2014 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-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./a.out...done.
(gdb) b do_something()
Breakpoint 1 at 0x4008a3: file lambda.cpp, line 4.
(gdb) run
Starting program: /home/alper/cplusplus/a.out
Breakpoint 1, do_something () at lambda.cpp:4
4 std::cout << "blah blah" << std::endl;
Missing separate debuginfos, use:
(gdb) n
blah blah
11 lambda_func();
Run Code Online (Sandbox Code Playgroud)
拆卸 do_something
(gdb) disassemble do_something
Dump of assembler code for function do_something():
0x40089b <+0>: push %rbp
0x40089c <+1>: mov %rsp,%rbp
0x40089f <+4>: sub $0x10,%rsp
=> 0x4008a3 <+8>: mov $0x4009fb,%esi
0x4008a8 <+13>: mov $0x601060,%edi
0x4008ad <+18>: callq 0x400750 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
0x4008b2 <+23>: mov $0x400770,%esi
0x4008b7 <+28>: mov %rax,%rdi
0x4008ba <+31>: callq 0x400760 <_ZNSolsEPFRSoS_E@plt>
0x4008bf <+36>: lea -0x1(%rbp),%rax
0x4008c3 <+40>: mov %rax,%rdi
0x4008c6 <+43>: callq 0x400870 <__lambda0::operator()() const>
0x4008cb <+48>: mov $0x400a05,%esi
0x4008d0 <+53>: mov $0x601060,%edi
0x4008d5 <+58>: callq 0x400750 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
0x4008da <+63>: mov $0x400770,%esi
0x4008df <+68>: mov %rax,%rdi
0x4008e2 <+71>: callq 0x400760 <_ZNSolsEPFRSoS_E@plt>
0x4008e7 <+76>: nop
0x4008e8 <+77>: leaveq
0x4008e9 <+78>: retq
Run Code Online (Sandbox Code Playgroud)
GDB输出行,callq 0x400870 <__lambda0::operator()() const>因此转换0x400870为函数指针并调用它.
(gdb) call ((void (*)()) 0x400870)()
in lambda
(gdb) call ((void (*)()) 0x400870)()
in lambda
(gdb) call ((void (*)()) 0x400870)()
in lambda
Run Code Online (Sandbox Code Playgroud)
注意:如果GCC内联lambda,则无需调用.例如,如果上面的示例是使用优化开关编译的-O3,则__lambda0::operator()() constGDB disassemble输出中没有行.
| 归档时间: |
|
| 查看次数: |
1918 次 |
| 最近记录: |