#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;
}
在这个示例程序中,如果编译(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
...
但是,如果您尝试调用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
GDB有点吓坏了。所以我的问题是:你如何在GDB中调用lambda?询问GDB与正常函数相比,它所期望的东西没有任何兴趣:
(gdb) whatis lambda_func
type = __lambda0
(gdb) whatis do_something
type = void (void)
我去看看lambda_func是否有任何特殊成员,例如一个调用的函数指针,类似于std :: function和/或std :: bind:
(gdb) print lambda_func
$1 = {<No data fields>}
没有特别会员?好吧也许它只是一个美化的函数指针?
(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.
所以我甚至不能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的64位Ubuntu 14.04
答案 0 :(得分:6)
我期待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
...
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();
反汇编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
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
注意:如果GCC内联lambda,则无需调用。例如,如果上面的示例是使用优化开关-O3
编译的,则GDB __lambda0::operator()() const
输出中没有disassemble
行。
答案 1 :(得分:1)
在一个不太合成的用例中,我成功地将 lambda 调用为
call myLambda.operator()(param1,param2)
但在 OP GDB 的测试用例中,似乎认为该函数是内联的——即使它不是。我已将此报告为 bug 28137。