GDB

2014-06-20 5 views
12
#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

(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 
... 

हालांकि, अगर आप तो कॉल करने के लिए लैम्ब्डा का प्रयास करें:

(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 क्या यह उम्मीद ब्याज की कुछ भी नहीं पता चलता है जब एक सामान्य कार्य की तुलना में:

(gdb) whatis lambda_func 
type = __lambda0 
(gdb) whatis do_something 
type = void (void) 

मैं अगर lambda_func किसी विशेष के सदस्यों, जैसे एक समारोह सूचक, कॉल std के सदृश करने के लिए :: समारोह और/या देखने के लिए चला गया 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()(), कोई लाभ नहीं हुआ सब।

Google पर एक खोज लैम्बडास में ब्रेकपॉइंट्स सेट करने के बारे में चीजों को प्रकट करती है, लेकिन डीबगर से उन लैम्बडा को कॉल करने के तरीके पर कुछ भी नहीं बताती है।

क्या इसके लायक है के लिए, यह Ubuntu 14.04 पर है 64-बिट जी का उपयोग कर ++ 4.8.2-19ubuntu1 और gdb 7.7-0ubuntu3.1

+0

'lambda_func.operator()' काम को कॉल कर रहा है? – John

+0

यह नहीं है। मैंने अतिरिक्त रूप से 'lambda_func.operator()() ',' lambda_func :: ऑपरेटर() ',' lambda_func :: ऑपरेटर()() ',' कॉल __lambda0', 'कॉल __lambda0()' कॉल करें, कॉल करें ' __lambda0 :: ऑपरेटर() ', 'कॉल __lambda0 :: ऑपरेटर()()', सभी को कोई फायदा नहीं हुआ। – inetknght

+0

lldb एक अलग त्रुटि संदेश देता है: 'त्रुटि: किसी फ़ंक्शन पर कॉल करें' $ _0 :: ऑपरेटर()() const '(' _ZNK3 $ _0clEv ') जो लक्ष्य त्रुटि में मौजूद नहीं है: चेतावनी: फ़ंक्शन' <अज्ञात कक्षा> :: ऑपरेटर() 'में आंतरिक संबंध है लेकिन त्रुटि परिभाषित नहीं है: अभिव्यक्ति को लक्ष्य में चलाने के लिए तैयार नहीं किया जा सका' – tclamb

उत्तर

6

मैं call __lambdaX::operator()() काम करता है उम्मीद कर रहा था, लेकिन ऐसा नहीं है। मुझे लगता है कि यह जीसीसी कार्यान्वयन से संबंधित है। मुझे यकीन नहीं है कि कोई बेहतर तरीका है लेकिन जब मैं जीडीबी में लैम्ब्डा को फोन करने की ज़रूरत है तो यह मेरा कामकाज समाधान है।

संक्षिप्त रूप से, जीडीबी में disassemble कमांड है और यह 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 <[email protected]> 
    0x4008b2 <+23>: mov $0x400770,%esi 
    0x4008b7 <+28>: mov %rax,%rdi 
    0x4008ba <+31>: callq 0x400760 <[email protected]> 
    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 <[email protected]> 
    0x4008da <+63>: mov $0x400770,%esi 
    0x4008df <+68>: mov %rax,%rdi 
    0x4008e2 <+71>: callq 0x400760 <[email protected]> 
    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 

नोट: यदि जीसीसी लैम्ब्डा को रेखांकित करता है, तो कॉल करने के लिए कुछ भी नहीं है। उदाहरण के लिए, यदि उपरोक्त उदाहरण ऑप्टिमाइज़ेशन स्विच -O3 के साथ संकलित किया गया है, तो GDB disassemble आउटपुट में __lambda0::operator()() const के साथ कोई लाइन नहीं है।

+0

वास्तव में एक आदर्श समाधान नहीं है, यह निश्चित रूप से शून्य() फ़ंक्शन को कॉल करने की क्षमता प्रदान करता है। कुछ के आसपास खेलने के साथ, मुझे यकीन है कि मैं यह भी पता लगा सकता हूं कि लैम्बडा को अन्य हस्ताक्षरों के साथ कैसे कॉल करें। धन्यवाद! – inetknght

 संबंधित मुद्दे