क्यों GDB लाइनों और प्रिंट चर के बीच अप्रत्याशित रूप से कूदता है "के रूप में मूल्य <> बाहर अनुकूलित?"


84

क्या कोई जीडीबी के इस व्यवहार की व्याख्या कर सकता है?

900         memset(&new_ckpt_info,'\0',sizeof(CKPT_INFO));
(gdb)
**903         prev_offset   = cp_node->offset;**
(gdb)
**905         m_CPND_CKPTINFO_READ(ckpt_info,(char *)cb->shm_addr.ckpt_addr+sizeof(CKPT_** HDR),i_offset);
(gdb)
**903         prev_offset   = cp_node->offset;**
(gdb)
**905         m_CPND_CKPTINFO_READ(ckpt_info,(char *)cb->shm_addr.ckpt_addr+sizeof(CKPT_ HDR),i_offset);**
(gdb)
**908         bitmap_offset  = client_hdl/32;**
(gdb)
**910         bitmap_value = cpnd_client_bitmap_set(client_hdl%32);**
(gdb)
**908         bitmap_offset  = client_hdl/32;**
(gdb)
**910         bitmap_value = cpnd_client_bitmap_set(client_hdl%32);**
(gdb)
**908         bitmap_offset  = client_hdl/32;**
(gdb)
**910         bitmap_value = cpnd_client_bitmap_set(client_hdl%32);**
(gdb)
913         found = cpnd_find_exact_ckptinfo(cb , &ckpt_info , bitmap_offset , &offset , &prev_offset);
(gdb)
916         if(!found)
(gdb) p found
$1 = <value optimized out>
(gdb) set found=0
Left operand of assignment is not an lvalue.

लाइन 903 को निष्पादित करने के बाद फिर से 905 908 910 के लिए इसे क्यों निष्पादित किया जाता है?

एक और चीज foundएक bool-टाइप वेरिएबल है, तो यह क्यों दिख रहा है value optimized out? मैं इसका मान भी सेट नहीं कर पा रहा हूं found

यह एक कंपाइलर ऑप्टिमाइज़ेशन लगता है (इस मामले में इसके -O2); मैं अभी भी का मूल्य कैसे निर्धारित कर सकता हूं found?


8
डिबगिंग के दौरान, यह आमतौर पर -O0 के साथ संकलन करने के लिए एक अच्छा विचार है क्योंकि अनुकूलन इस तरह की समस्याओं की ओर जाता है।
LiraNuna

जवाबों:


115

अनुकूलित कोड डिबग करने के लिए, विधानसभा / मशीन भाषा सीखें।

GDB TUI मोड का उपयोग करें। GDB की मेरी प्रतिलिपि इसे तब सक्षम करती है जब मैं ऋण दर्ज करता हूं और दर्ज करता हूं। फिर Cx 2 टाइप करें (जो कि नियंत्रण और X दबाकर रखें, दोनों को छोड़ें और फिर 2 दबाएं)। वह इसे स्प्लिट सोर्स और डिसएस्पॉज़ डिस्प्ले में डाल देगा। फिर एक समय में एक मशीन निर्देश का उपयोग करने stepiऔर nextiस्थानांतरित करने के लिए। TUI विंडो के बीच स्विच करने के लिए Cx o का उपयोग करें।

अपने सीपीयू की मशीन भाषा और फ़ंक्शन कॉलिंग सम्मेलनों के बारे में एक पीडीएफ डाउनलोड करें। आप फ़ंक्शन तर्कों और वापसी मूल्यों के साथ क्या किया जा रहा है, इसे पहचानना जल्दी सीखेंगे।

आप जैसे GDB कमांड का उपयोग करके किसी रजिस्टर का मान प्रदर्शित कर सकते हैं p $eax


मेरे पास अभी भी "अनुकूलित आउट" समस्या है, और चर मान अन्य विंडो में नहीं दिखाया गया है, लेकिन, फिर भी, यह एक महान जानकारी है, धन्यवाद!
टॉम ब्रिटो

16
@ टोमब्रिटो: ऑप्टिमाइज़ आउट का मतलब है कि चर स्मृति में नहीं है। यह शायद सीपीयू रजिस्टर में ही होता है, जिसका अर्थ है कि आपको डिस्सैम्ड पढ़ने की जरूरत है और इसे खोजने के लिए रजिस्टर वैल्यू को प्रिंट करना होगा।
ज़ैन लिंक्स

@Zan Lynx: मुझे यकीन नहीं है कि मैं आपके विश्लेषण से सहमत हूँ। DWARF प्रतीकों में रजिस्टरों से मान निकालने के लिए पर्याप्त जानकारी है। शायद यहां इसका मतलब यह है कि संकलक ने निर्धारित किया है कि चर को मौजूदा लाइन तक पहुंचने वाले समय तक सुरक्षित रूप से खारिज किया जा सकता है। उस स्थिति में भंडारण जहां चर जीवन संभवत: किसी और चीज के लिए पुन: उपयोग किया गया है। मुझे लगता है कि आप सही हैं कि यह सामान्य रूप से केवल तभी होगा जब चर की परिकल्पना की गई थी, हालांकि।
इयान नी-लुईस

@ इयानि-लुईस: मुझे नहीं पता कि आप DWARF के किस संस्करण का उपयोग कर रहे हैं, लेकिन मेरे अनुभव में GDB एक चर को प्रिंट नहीं कर सकता है जिसे एक रजिस्टर में संग्रहीत किया गया है।
ज़ेन लिंक्स

मुझे यकीन है कि आप सही हैं। DWARF के साथ मेरा अनुभव अपने स्वयं के पार्सर लिखने से आता है, gdb का उपयोग करने से नहीं, इसलिए मैं वास्तव में नहीं जानता कि gdb क्या करने में सक्षम है।
इयान नी-लुईस

75

अनुकूलन के बिना पुनरावर्ती (जीसीसी पर -0)।


17
भी -00 अनुकूलित कोड का उत्पादन कर सकते हैं (अभी इस के साथ संघर्ष करने की कोशिश कर रहा है), हालांकि मुझे यकीन नहीं है कि क्यों।
क्रिस ग्रेग

@ क्रिसग्रेग मुझे एक ही समस्या है! क्या आपको पता है कि मुद्दा क्या है?
पाओलो एम।

1
@paolom ऐसा लगता है कि यह एक क्लैंग इश्यू हो सकता है, इसलिए मैं डिबगिंग उद्देश्यों के लिए जी ++ के साथ संकलन कर रहा हूं, दुर्भाग्य से।
क्रिस ग्रीग

अक्सर यह एक समाधान नहीं है - खासकर यदि आपके पास उत्पादन से एक कोर डंप है और / या आप विकास पर्यावरण पर समस्या को पुन: पेश करने में असमर्थ हैं।
स्मियर

39

घोषणा "अस्थिर" के रूप में मिली । यह संकलक को यह बताना चाहिए कि इसका अनुकूलन न करें।

volatile int found = 0;

1
यहां तक ​​कि जब मैं gdb डिबगर में कुछ चर "अस्थिर" घोषित करता हूं, तो यह इसे बाहर से अनुकूलित चर के रूप में दिखाता है! क्या अब इसमें नहीं है?
M.Rez

11

संकलक चालू किए गए अनुकूलन के साथ बहुत चालाक चीजें करना शुरू कर देगा। डिबगर कोड को आगे और पीछे की तरफ कूदते हुए दिखाएगा, क्योंकि रजिस्टरों में अनुकूलित तरीके वैरिएबल संग्रहित हैं। शायद यही कारण है कि आप अपने चर (या कुछ मामलों में इसके मूल्य को देख सकते हैं) को सेट नहीं कर सकते हैं क्योंकि यह स्पीड मेमोरी के लिए रजिस्टरों के बीच वितरित किया गया है, बजाय एक डायरेक्ट मेमोरी लोकेशन के जिसे डिबगर एक्सेस कर सकता है।

अनुकूलन के बिना संकलन?


6

आमतौर पर, बूलियन मान जो शाखाओं में उपयोग किए जाते हैं, वे इस तरह की गणना के तुरंत बाद वैरिएबल में कभी संग्रहीत नहीं होते हैं। इसके बजाय, कंपाइलर सीधे उन शर्त कोडों को सीधे शाखा देता है जो पूर्ववर्ती तुलना से निर्धारित किए गए थे। उदाहरण के लिए,

int a = SomeFunction();
bool result = --a >= 0; // use subtraction as example computation
if ( result ) 
{
   foo(); 
}
else
{
   bar();
}
return;

आमतौर पर कुछ इस तरह के संकलन:

call .SomeFunction  ; calls to SomeFunction(), which stores its return value in eax
sub eax, 1 ; subtract 1 from eax and store in eax, set S (sign) flag if result is negative
jl ELSEBLOCK ; GOTO label "ELSEBLOCK" if S flag is set
call .foo ; this is the "if" black, call foo()
j FINISH ; GOTO FINISH; skip over the "else" block
ELSEBLOCK: ; label this location to the assembler
call .bar
FINISH: ; both paths end up here
ret ; return

ध्यान दें कि "बूल" वास्तव में कहीं भी संग्रहीत नहीं है।


4

आप बहुत अधिक पाया का मूल्य निर्धारित नहीं कर सकते। डिबगिंग अनुकूलित प्रोग्राम शायद ही कभी परेशानी के लायक होते हैं, कंपाइलर कोड को उन तरीकों से पुनर्व्यवस्थित कर सकता है, जो किसी भी तरह से स्रोत कोड (समान परिणाम उत्पन्न करने के अलावा) के अनुरूप नहीं होंगे, इस प्रकार डिबगर्स को कोई अंत नहीं होने देता।


4

जब डिबगिंग ऑप्टिमाइज़्ड प्रोग्राम (जो आवश्यक हो सकता है यदि बग डिबग बिल्ड में दिखाई नहीं देता है), तो आपको अक्सर असेंबली कंपाइलर को समझना होगा।

आपके विशेष मामले में, वापसी मूल्य cpnd_find_exact_ckptinfoको रजिस्टर में संग्रहीत किया जाएगा जो आपके प्लेटफॉर्म पर रिटर्न वैल्यू के लिए उपयोग किया जाता है। पर ix86, यह होगा %eax। पर x86_64:, %raxआदि यदि आप उपरोक्त में से कोई नहीं हैं, तो आपको [[आपके प्रोसेसर] प्रक्रिया कॉलिंग कन्वेंशन ’के लिए Google की आवश्यकता हो सकती है।

आप उस रजिस्टर की जांच GDBकर सकते हैं और उसे सेट कर सकते हैं। जैसे ix86:

(gdb) p $eax
(gdb) set $eax = 0 

0

Gdb के साथ QtCreator का उपयोग कर Im।

जोड़ा जा रहा है

QMAKE_CXXFLAGS += -O0
QMAKE_CXXFLAGS -= -O1
QMAKE_CXXFLAGS -= -O2
QMAKE_CXXFLAGS -= -O3

मेरे लिए अच्छा काम करता है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.