2011-08-03 22 views
67

लिनक्स विशिष्ट backtrace() और backtrace_symbols() आपको प्रोग्राम का कॉल ट्रेस बनाने की अनुमति देता है। हालांकि, यह केवल फ़ंक्शन पते प्रिंट करता है, न कि मेरे कार्यक्रम के लिए उनके नाम। मैं उन्हें फ़ंक्शन नामों को भी प्रिंट कैसे कर सकता हूं? मैंने प्रोग्राम को -g के साथ-साथ -ggdb के साथ संकलित करने का प्रयास किया है। बस नीचे दिए गए परीक्षण का मामला इस प्रिंट:बैकट्रैक()/backtrace_symbols() फ़ंक्शन नाम प्रिंट करने के लिए कैसे करें?

 

    BACKTRACE ------------ 
    ./a.out() [0x8048616] 
    ./a.out() [0x8048623] 
    /lib/libc.so.6(__libc_start_main+0xf3) [0x4a937413] 
    ./a.out() [0x8048421] 
    ---------------------- 

मैं पहली बार 2 आइटम चाहते हैं समारोह के नाम, foo और main

कोड भी दिखाने के लिए:

#include <execinfo.h> 
#include <string.h> 
#include <errno.h> 
#include <unistd.h> 
#include <stdlib.h> 

static void full_write(int fd, const char *buf, size_t len) 
{ 
     while (len > 0) { 
       ssize_t ret = write(fd, buf, len); 

       if ((ret == -1) && (errno != EINTR)) 
         break; 

       buf += (size_t) ret; 
       len -= (size_t) ret; 
     } 
} 

void print_backtrace(void) 
{ 
     static const char start[] = "BACKTRACE ------------\n"; 
     static const char end[] = "----------------------\n"; 

     void *bt[1024]; 
     int bt_size; 
     char **bt_syms; 
     int i; 

     bt_size = backtrace(bt, 1024); 
     bt_syms = backtrace_symbols(bt, bt_size); 
     full_write(STDERR_FILENO, start, strlen(start)); 
     for (i = 1; i < bt_size; i++) { 
       size_t len = strlen(bt_syms[i]); 
       full_write(STDERR_FILENO, bt_syms[i], len); 
       full_write(STDERR_FILENO, "\n", 1); 
     } 
     full_write(STDERR_FILENO, end, strlen(end)); 
    free(bt_syms); 
} 
void foo() 
{ 
    print_backtrace(); 
} 

int main() 
{ 
    foo(); 
    return 0; 
} 
+0

के संभावित डुप्लिकेट [कैसे और अधिक विस्तृत नामों को प्राप्त करने] (http://stackoverflow.com/questions/5945775 (न सिर्फ इस बात के लिए एक खाता बनाने के लिए, यदि आप इसे कठिन पसंद नहीं है के लिए जा रहा)/कैसे-से-अधिक-विस्तृत-बैकट्रैक) – Nemo

+0

http://stackoverflow.com/questions/105659/how-can-one-grab-a-stack-trace-in-c –

उत्तर

46

प्रतीकों लिया जाता है गतिशील प्रतीक तालिका से; आपको -rdynamic विकल्प gcc पर विकल्प है, जो इसे लिंकर पर एक झंडा पास करता है जो सुनिश्चित करता है कि सभी प्रतीकों को तालिका में रखा गया है।

+8

हालांकि यह स्थिर प्रतीकों के लिए काम नहीं करता है। 'libunwind' कि @Nemo उल्लेख करता है, स्थिर कार्यों के लिए काम करता है। –

25

उपयोग addr2line command (GCC manual की Link Options पृष्ठ देखें, और/या glibc manual की Backtraces पेज।) स्रोत कोड फ़ाइल नाम + लाइन नंबर के लिए निष्पादन योग्य पते कैसे मैप करने के लिए। फ़ंक्शन नाम प्राप्त करने के लिए -f विकल्प भी दें।

वैकल्पिक रूप से, libunwind आज़माएं।

+3

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

+0

... और एएसएलआर स्थानान्तरण के साथ पहले से कहीं अधिक आम हैं। –

+0

@ErwanLegrand: एएसएलआर से पहले, मैंने सोचा था कि स्थानान्तरण अनुमानित थे और 'addr2line' ने साझा वस्तुओं (?) में पते के लिए भी भरोसेमंद काम किया था, लेकिन हाँ, आधुनिक प्लेटफार्मों पर आपको स्थानांतरित करने योग्य वस्तु के वास्तविक लोड पते को भी जानने की आवश्यकता होगी सिद्धांत में यह ऑपरेशन। – Nemo

9

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

Libbacktrace को सभी प्रतीकों को निर्यात करने की आवश्यकता नहीं है, जो बदसूरत होगा, और एएसएलआर इसे तोड़ नहीं देता है।

लिबैकट्रैक मूल रूप से जीसीसी वितरण का हिस्सा था। अब, एक स्टैंडअलोन संस्करण Github पर पाया जा सकता:

https://github.com/ianlancetaylor/libbacktrace

1

शीर्ष पर जवाब एक बग अगर सेवानिवृत्त == -1 है और errno EINTER है आप फिर से कोशिश करना चाहिए, लेकिन के रूप में की नकल की सेवानिवृत्त गिनती नहीं

static void full_write(int fd, const char *buf, size_t len) 
{ 
     while (len > 0) { 
       ssize_t ret = write(fd, buf, len); 

       if ((ret == -1) { 
         if (errno != EINTR)) 
           break; 
         //else 
         continue; 
       } 
       buf += (size_t) ret; 
       len -= (size_t) ret; 
     } 
} 
संबंधित मुद्दे