2012-06-25 13 views
10

मेरे सी ++ कोड में होने वाली अधिकांश त्रुटियों से ऐप को बाहर निकलने का कारण बनता है, बिना लॉगकाट आउटपुट के, और डिवाइस पर कोई संदेश नहीं। नल पॉइंटर्स और जेएनआई का गलत उपयोग अक्सर इस परिणाम का उत्पादन करता है, और कहने की जरूरत नहीं है, यह डीबगिंग को बहुत कठिन बनाता है।क्या एंड्रॉइड ऐप क्रैश होने पर मुझे सी ++ स्टैक ट्रेस मिल सकता है?

वर्तमान में मैं ndk-gdb में 'बीटी' कमांड के साथ एक स्टैक ट्रेस प्राप्त कर सकता हूं, लेकिन अगर क्रैश स्टार्टअप के पहले 2 सेकंड के भीतर होता है, क्योंकि ndk-gdb प्रक्रिया शुरू करता है और इसके बाद इसे संलग्न करता है शुरू कर दिया है। इसके अलावा, ndk-gdb अविश्वसनीय है, अक्सर यह कहता है कि यह कोई प्रतीक नहीं ढूंढ सकता है, या उदाहरण के लिए गैर-घातक "सिगिल" त्रुटियों के बारे में शिकायत नहीं कर सकता है।

क्या कोई ऐप क्रैश होने पर त्रुटि को फँसाने और स्टैक ट्रेस प्रिंट करने या अन्य जानकारी प्रिंट करने का कोई तरीका है? उदाहरण के लिए, यदि कोई SIGSEGV था, तो मैं जानना चाहता हूं कि ऐप किस पते का उपयोग करने का प्रयास कर रहा था।

+1

इस उत्तर को चेक करें। यह विशेष रूप से एंड्रॉइड http://stackoverflow.com/a/28858941/365229 –

उत्तर

4

trace.txt फ़ाइल कुछ दे? मुझे याद नहीं है कि उसका स्थान है: /data/anr/trace.txt या /data/data/{pkg}/trace.txt

1

आपको सीजीवी प्राप्त करने पर कोड निष्पादित करने के लिए SIGSEGV को फंसाने से शुरू करना होगा। यह POSIX कोड है, इसलिए कुछ इसी तरह एंड्रॉयड पर काम करना चाहिए:

void abortHandler(int signum, siginfo_t* si, void* unused) 
{ 
    const char* name = NULL; 
    switch(signum) 
    { 
    case SIGABRT: name = "SIGABRT"; break; 
    case SIGSEGV: name = "SIGSEGV"; break; 
    case SIGBUS: name = "SIGBUS"; break; 
    case SIGILL: name = "SIGILL"; break; 
    case SIGFPE: name = "SIGFPE"; break; 
    case SIGPIPE: name = "SIGPIPE"; break; 
    } 

    if (name) 
     printf(stderr, "Caught signal %d (%s)\n", signum, name); 
    else 
     printf(stderr, "Caught signal %d\n", signum); 

    printStackTrace(stderr); 

    exit(signum); 
} 

void handleCrashes() 
{ 
    struct sigaction sa; 
    sa.sa_flags = SA_SIGINFO; 
    sa.sa_sigaction = abortHandler; 
    sigemptyset(&sa.sa_mask); 

    sigaction(SIGABRT, &sa, NULL); 
    sigaction(SIGSEGV, &sa, NULL); 
    sigaction(SIGBUS, &sa, NULL); 
    sigaction(SIGILL, &sa, NULL); 
    sigaction(SIGFPE, &sa, NULL); 
    sigaction(SIGPIPE, &sa, NULL); 
} 

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

void printStackTrace(unsigned int max_frames = 63) 
{ 
    void* addrlist[max_frames+1]; 

    // retrieve current stack addresses 
    u32 addrlen = backtrace(addrlist, sizeof(addrlist)/sizeof(void*)); 

    if (addrlen == 0) 
    { 
     printf(stderr, " <empty, possibly corrupt>\n"); 
     return; 
    } 

    char** symbollist = backtrace_symbols(addrlist, addrlen); 

    for (u32 i = 3; i < addrlen; i++) 
     printf(stderr, "%s\n", symbollist[i]): 
} 

आप उन्हें पठनीय बनाने के लिए प्रतीकों demangle के लिए और अधिक काम करने की आवश्यकता होगी:

एक स्टैक ट्रेस मुद्रित करने के लिए। abi :: __ cxa_demangle आज़माएं। निश्चित रूप से -g और साथ-साथ लिंक के साथ लिंक।

+0

धन्यवाद के लिए है। मैंने उस बग को ठीक किया जिसे मैं ढूंढ रहा था लेकिन अगली बार मैं इसे निश्चित रूप से एक शॉट दूंगा। मुझे यकीन नहीं है कि मैं '-गतिशील' समझता हूं, हालांकि मैंने प्रलेखन को देखा: "इसका समर्थन करने वाले लक्ष्यों पर, ईएलएफ लिंकर को फ्लैग-एक्सपोर्ट-डायनामिक पास करें। यह लिंकर को सभी प्रतीकों को जोड़ने के लिए निर्देशित करता है, न केवल उपयोग किया जाता है गतिशील प्रतीक तालिका में। इस विकल्प को डलोपेन के कुछ उपयोगों के लिए या प्रोग्राम के भीतर से बैकट्रैक प्राप्त करने की अनुमति देने के लिए आवश्यक है। " ('-g', इस बीच," लक्ष्य के लिए पसंदीदा प्रारूप में डीबगिंग जानकारी चालू करता है "। – Qwertie

+9

बकवास! बैकट्रैक execinfo.h में होना चाहिए, लेकिन यह एंड्रॉइड पर मौजूद नहीं है! (execinfo.h: ऐसी कोई फ़ाइल या निर्देशिका नहीं) – Qwertie

+3

हाँ, एंड्रॉइड पर कोई 'बैकट्रैक' नहीं है। –

-2

हाँ, 'execinfo.h' वहाँ मौजूद नहीं है, लेकिन CallStack करता है:

#include <utils/CallStack.h> 
.. 
CallStack cs; 
cs.dump(); 

आशा है कि यह इस तरह के संकेत हैंडलर में मदद कर सकते हैं।

+0

मुझे कुछ याद आना चाहिए: घातक त्रुटि: utils/CallStack.h: ऐसी कोई फ़ाइल या निर्देशिका # शामिल नहीं है --- शायद कुछ और है जो Android.mk या कुछ में जाने की आवश्यकता है? –

+3

एनडीके फ़ोल्डर में कोई फ़ाइल 'CallStack.h' नहीं है! –

+0

https://android.googlesource.com/platform/system/core.git/+/master/include/utils/CallStack.h https://android.googlesource.com/platform/frameworks/native/+/jb- dev/include/utils/CallStack.h –

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