c++ - कार्यक्रम केवल रिलीज बिल्ड के रूप में दुर्घटनाग्रस्त हो जाता है-डीबग कैसे करें?




debugging (18)

मुझे यहां "श्राइडरिंगर कैट" प्रकार की समस्या है - मेरा प्रोग्राम (वास्तव में मेरे प्रोग्राम के लिए टेस्ट सूट, लेकिन फिर भी एक प्रोग्राम) क्रैश हो रहा है, लेकिन केवल रिलीज मोड में बनाया गया है, और केवल कमांड लाइन से लॉन्च होने पर । गुफाओं के डिबगिंग (यानी, गंदा प्रिंटफ () संदेशों के माध्यम से सभी जगहों पर), मैंने टेस्ट विधि निर्धारित की है जहां कोड क्रैश हो रहा है, दुर्भाग्यवश दुर्भाग्यवश कुछ विनाशक में वास्तविक दुर्घटना होती है, क्योंकि आखिरी ट्रेस संदेश जो मैं देख रहा हूं अन्य विनाशक जो साफ-सफाई निष्पादित करते हैं।

जब मैं विजुअल स्टूडियो के अंदर इस प्रोग्राम को चलाने का प्रयास करता हूं, तो यह क्रैश नहीं होता है। WinDbg.exe से लॉन्च करते समय वही चला जाता है। क्रैश केवल तभी होता है जब कमांड लाइन से लॉन्च होता है। यह विंडोज विस्टा, बीटीडब्ल्यू के तहत हो रहा है, और दुर्भाग्यवश मुझे परीक्षण करने के लिए अभी एक एक्सपी मशीन तक पहुंच नहीं है।

यह वास्तव में अच्छा होगा अगर मैं एक स्टैक ट्रेस प्रिंट करने के लिए विंडोज़ प्राप्त कर सकता हूं, या प्रोग्राम को समाप्त करने के अलावा कुछ और जैसे कि यह साफ़ हो गया था। क्या किसी के पास कोई सलाह है कि मैं यहां कुछ और सार्थक जानकारी कैसे प्राप्त कर सकता हूं और उम्मीद है कि इस बग को ठीक कर दें?

संपादित करें: समस्या वास्तव में बाहर की बाउंड सरणी के कारण हुई थी, जिसे मैं इस पोस्ट में और अधिक बताता हूं । इस समस्या को खोजने में आपकी मदद के लिए सभी को धन्यवाद!


संलग्न डीबगर के साथ Ntdll.dll

आईडीई या विन डीबीजी से प्रोग्राम लॉन्च करने के बीच एक छोटा सा अंतर अंतर कमांड लाइन / डेस्कटॉप से ​​लॉन्च करने के विरोध में है कि जब एक डीबगर संलग्न (यानी आईडीई या विन डीबीजी) के साथ लॉन्च करते समय ntdll.dll एक अलग ढेर कार्यान्वयन का उपयोग करता है जो कुछ कम सत्यापन करता है स्मृति आवंटन / मुक्त करने पर।

आप ntdll.dll में अप्रत्याशित उपयोगकर्ता ब्रेकपॉइंट में कुछ प्रासंगिक जानकारी पढ़ सकते हैं। एक उपकरण जो समस्या की पहचान करने में आपकी सहायता करने में सक्षम हो सकता है PageHeap.exe

क्रैश विश्लेषण

आपने लिखा नहीं है कि आप "क्रैश" क्या अनुभव कर रहे हैं। एक बार प्रोग्राम क्रैश हो जाता है और आपको Microsoft को त्रुटि जानकारी भेजने की पेशकश करता है, तो आप तकनीकी जानकारी पर क्लिक करने और कम से कम अपवाद कोड को जांचने में सक्षम होना चाहिए, और कुछ प्रयासों के साथ आप पोस्ट- मॉर्टम विश्लेषण भी कर सकते हैं ( Heisenbug देखें : कुछ कंप्यूटरों पर WinApi प्रोग्राम क्रैश) निर्देशों के लिए)


Vista SP1 वास्तव में सिस्टम में निर्मित वास्तव में एक अच्छा क्रैश डंप जेनरेटर है। दुर्भाग्य से, यह डिफ़ॉल्ट रूप से चालू नहीं है!

यह आलेख देखें: http://msdn.microsoft.com/en-us/library/bb787181(VS.85).aspx

इस दृष्टिकोण का लाभ यह है कि प्रभावित सिस्टम पर कोई अतिरिक्त सॉफ्टवेयर स्थापित करने की आवश्यकता नहीं है। पकड़ो और इसे चीर, बच्चे!


आप WinDbg को अपने पोस्टमॉर्टम डीबगर के रूप में सेट कर सकते हैं। यह डीबगर लॉन्च करेगा और क्रैश होने पर प्रक्रिया को संलग्न करेगा। पोस्टमॉर्टम डीबगिंग के लिए WinDbg इंस्टॉल करने के लिए, / I विकल्प का उपयोग करें (ध्यान दें कि यह पूंजीकृत है ):

windbg /I

here अधिक जानकारी।

कारण के रूप में, यह संभवतः एक प्रारंभिक चर है क्योंकि अन्य उत्तरों का सुझाव है।


आप ग्लोबल फ्लैग सक्षम (विंडोज़ के लिए डिबगिंग टूल्स में देखें) के साथ अपना सॉफ़्टवेयर चला सकते हैं। यह अक्सर समस्या को दूर करने में मदद करेगा।


इस तरह की त्रुटि को डीबग करने का एक शानदार तरीका है अपने डीबग बिल्ड के लिए अनुकूलन सक्षम करना।


इस तरह के क्रैश लगभग हमेशा होते हैं क्योंकि एक आईडीई आमतौर पर शून्य, शून्य या कुछ अन्य 'समझदार' मान में अनियमित चर की सामग्री सेट करेगा, जबकि जब आप मूल रूप से चल रहे हों तो आपको सिस्टम जो भी यादृच्छिक बकवास मिल जाएगा।

इसलिए आपकी त्रुटि लगभग निश्चित रूप से है कि आप कुछ उपयोग कर रहे हैं जैसे कि आप ठीक से प्रारंभ होने से पहले एक पॉइंटर का उपयोग कर रहे हैं और आप आईडीई में इससे दूर हो रहे हैं क्योंकि यह कहीं भी खतरनाक नहीं है - या मूल्य आपके द्वारा संभाला जाता है त्रुटि जांच - लेकिन रिलीज मोड में यह कुछ बुरा करता है।


कभी-कभी ऐसा होता है क्योंकि आपने "जोर" मैक्रो के अंदर महत्वपूर्ण ऑपरेशन लपेट लिया है। जैसा कि आप जानते हैं, "जोर दें" केवल डीबग मोड पर अभिव्यक्ति का मूल्यांकन करता है।


क्रैश डंप करने के लिए आप विश्लेषण कर सकते हैं:

  1. अपने कोड के लिए पीडीबी फाइलें जेनरेट करें।
  2. आप एक ही पते में अपने exe और dlls लोड करने के लिए rebase।
  3. डॉ मॉर्टम जैसे पोस्ट मॉर्टम डीबगर सक्षम करें
  4. दुर्घटना खोजक जैसे उपकरण का उपयोग कर क्रैश विफलता पता जांचें।

आपको विंडोज़ के लिए डिबगिंग टूल में टूल्स भी देखना चाहिए। आप एप्लिकेशन की निगरानी कर सकते हैं और अपने पहले मौके अपवाद से पहले के पहले मौके अपवाद देख सकते हैं।

आशा करता हूँ की ये काम करेगा...


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


जब मुझे इस तरह की समस्याओं का सामना करना पड़ता है तो यह आमतौर पर चर प्रारंभिकरण के कारण होता है। डीबग मोड में, चर और पॉइंटर्स स्वचालित रूप से शून्य पर प्रारंभ हो जाते हैं लेकिन रिलीज़ मोड में वे नहीं करते हैं। इसलिए, यदि आपके पास ऐसा कोड है

int* p;
....
if (p == 0) { // do stuff }

डीबग मोड में कोड को निष्पादित नहीं किया गया है लेकिन रिलीज मोड पी में एक अपरिभाषित मान होता है, जो 0 होने की संभावना नहीं है, इसलिए कोड को अक्सर क्रैश होने के कारण निष्पादित किया जाता है।

मैं अनियमित चर के लिए अपना कोड जांचूंगा। यह सरणी की सामग्री पर भी लागू हो सकता है।


डायग्नोस्टिक जानकारी प्राप्त करने में आपकी समस्याओं के संबंध में, क्या आपने adplus.vbs का उपयोग WinDbg.exe के विकल्प के रूप में करने का प्रयास किया है? चलने की प्रक्रिया से जुड़ने के लिए, उपयोग करें

adplus.vbs -crash -p <process_id>

या घटना में प्रारंभ करने के लिए जब दुर्घटना जल्दी हो जाती है:

adplus.vbs -crash -sc your_app.exe

Adplus.vbs पर पूरी जानकारी यहां मिल सकती है: http://support.microsoft.com/kb/286350


डिबगिंग रिलीज बिल्ड्स ऑर्डर बदलने वाले अनुकूलन के कारण दर्द हो सकता है जिसमें आपके कोड की रेखाएं निष्पादित की जाती हैं। यह वास्तव में भ्रमित हो सकता है!

कम से कम समस्या को कम करने की एक तकनीक है संदेश बॉक्स () का उपयोग त्वरित विवरणों को प्रदर्शित करने के लिए करना है, यह बताते हुए कि आपके कोड को किस प्रोग्राम में मिला है ("Foo () प्रारंभ करना," Foo2 () प्रारंभ करना); उन्हें अपने कोड के क्षेत्र में फ़ंक्शंस के शीर्ष पर डालने लगें जो आपको संदेह है (उस समय आप क्या कर रहे थे जब यह दुर्घटनाग्रस्त हो गया था?)। जब आप कौन सा फ़ंक्शन बता सकते हैं, तो संदेश बॉक्स को कोड के ब्लॉक या उस फ़ंक्शन के भीतर भी व्यक्तिगत लाइनों में बदलें जब तक कि आप इसे कुछ पंक्तियों तक सीमित न करें। फिर आप चर के मूल्य को प्रिंट करना शुरू कर सकते हैं यह देखने के लिए कि वे क्रैश होने के बिंदु पर क्या स्थिति में हैं।


मुझे यह त्रुटि थी और बनाम भी कोशिश कर रहा था! साफ! मेरी परियोजना। तो मैंने रिलीज निर्देशिका से मैन्युअल रूप से obj फ़ाइलों को हटा दिया, और उसके बाद यह ठीक ठीक बनाया गया।


मेरे अनुभव के रूप में, यह स्मृति भ्रष्टाचार के मुद्दों में सबसे अधिक है।

उदाहरण के लिए :

char a[8];
memset(&a[0], 0, 16);

: /*use array a doing some thing */

जब कोई कोड चलाता है तो डीबग मोड में सामान्य होना बहुत संभव है।

लेकिन रिलीज में, यह क्रैश हो सकता है / हो सकता है।

मेरे लिए, गड़बड़ करने के लिए जहां स्मृति बाध्य है, बहुत कठिन है।

विजुअल लीक डिटेक्टर (विंडोज़) या valgrind (लिनक्स) जैसे कुछ टूल्स का उपयोग अधिक बुद्धिमान choise हैं।


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


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


यह संदिग्ध है कि यह डीबगर के बाहर होगा और अंदर नहीं; डीबगर में चलने से आमतौर पर एप्लिकेशन व्यवहार में बदलाव नहीं होता है। मैं कंसोल और आईडीई के बीच पर्यावरण मतभेदों की जांच करूंगा। इसके अलावा, जाहिर है, ऑप्टिमाइज़ेशन और डीबग जानकारी के बिना रिलीज संकलित करें, और देखें कि यह व्यवहार को प्रभावित करता है या नहीं। अंत में, पोस्ट-मॉर्टम डिबगिंग टूल को देखें, अन्य लोगों ने यहां सुझाव दिया है, आमतौर पर आप उनसे कुछ सुराग प्राप्त कर सकते हैं।


एक बार जब मुझे कोई समस्या हो तो ऐप आपके समान व्यवहार करता था। यह sprintf में एक बुरा बफर overrun हो गया। स्वाभाविक रूप से, यह एक डीबगर संलग्न के साथ चलाने के दौरान काम किया। मैंने जो किया, वह एक SetUnhandledExceptionFilter अपवाद फ़िल्टर ( SetUnhandledExceptionFilter ) स्थापित करना था जिसमें मैंने असीमित रूप से अवरुद्ध किया था (INFINITE के टाइमआउट मान के साथ एक बोगस हैंडल पर WaitForSingleObject का उपयोग करके)।

तो आप कुछ के साथ कुछ कर सकते हैं:

long __stdcall MyFilter(EXCEPTION_POINTERS *)
{
    HANDLE hEvt=::CreateEventW(0,1,0,0);
    if(hEvt)
    {
        if(WAIT_FAILED==::WaitForSingleObject(hEvt, INFINITE))
        {
            //log failure
        }
    }

}
// somewhere in your wmain/WinMain:
SetUnhandledExceptionFilter(MyFilter);

बग के बाद मैंने डीबगर को संलग्न किया था (गुई प्रोग्राम ने जवाब देना बंद कर दिया था)।

फिर आप या तो डंप ले सकते हैं और बाद में इसके साथ काम कर सकते हैं:

.dump / ma path_to_dump_file

या इसे तुरंत डीबग करें। सबसे आसान तरीका यह ट्रैक करना है कि प्रोसेसर संदर्भ को रनटाइम अपवाद हैंडलिंग मशीनरी द्वारा सहेजा गया है:

एसडी esp रेंज 1003 एफ

कमान CONTEXT रिकॉर्ड (एस) के लिए स्टैक एड्रेस स्पेस की खोज करेगा, जो खोज की लंबाई प्रदान करेगा। मैं आमतौर पर 'एल? 10000' जैसे कुछ का उपयोग करता हूं। नोट, अनचाहे अपवाद फ़िल्टर फ्रेम के निकट आमतौर पर रिकॉर्ड के रूप में असंख्य बड़ी संख्याओं का उपयोग न करें। 1003 एफ झंडे का संयोजन है (मुझे विश्वास है कि यह CONTEXT_FULL से मेल खाता है) प्रोसेसर राज्य को कैप्चर करने के लिए उपयोग किया जाता है। आपकी खोज इस तरह दिखती है:

0: 000> एसडी esp l1000 1003f
0012 सी 160 0001003 एफ 00000000 00000000 00000000? ...............

एक बार जब आप परिणाम प्राप्त कर लेंगे, तो cxr कमांड में पते का उपयोग करें:

सीसीआरआर 0012 सी 160

यह आपको क्रैश के समय बिल्कुल इस नए CONTEXT पर ले जाएगा (जब आप अपने ऐप को क्रैश करते हैं तो आपको बिल्कुल स्टैक ट्रेस मिलेगा)। इसके अतिरिक्त, उपयोग करें:

.exr -1

यह पता लगाने के लिए कि वास्तव में कौन सा अपवाद हुआ था।

आशा करता हूँ की ये काम करेगा।







debugging