से गलत रेखा संख्या मैं C++ प्रोग्राम में बैकट्रैक में कॉल की सटीक रेखा को खोजने का प्रयास करता हूं। अभी मैं (पश्व-अनुरेखन का आदमी पृष्ठ से) इन पंक्तियों का उपयोग कर रहा ट्रेस पाने के लिए:addr2line
void *bt_buffer[1000];
char **bt_strings;
int bt_nptrs = backtrace(bt_buffer, 1000);
bt_strings = backtrace_symbols(bt_buffer, bt_nptrs);
bt_strings मैं प्रपत्र की तर्ज
./prog() [0x402e42]
अब मैं पता लेने को खोजने में (हेक्स स्ट्रिंग) और addr2line को फ़ीड करें। कभी-कभी स्पष्ट रूप से गलत रेखा संख्याओं में परिणाम मिलता है। इंटरनेट खोज मुझे इस post, जिसमें यह दिखाया गया है कि
readelf -wl ./prog
इंगित करता है जहां लाइन वास्तव में है, या कहें कि कितने लाइनों प्रतीक वर्तमान लाइन के लिए ले जाया गया है का नेतृत्व किया।
संपादित करें: यह तब होता है जब मैं explicetly अनुकूलन के बिना -g -O0
साथ संकलन है, अर्थात। संकलक gcc 4.6.3
है क्या कोई अन्य कंपाइलर ध्वज है जिसे मैं याद करता हूं?
मेरी समस्या निम्न है: मुझे इसे स्वचालित करने की आवश्यकता है। मुझे बैकट्रैक (पूर्ण) बनाने के लिए अपने प्रोग्राम की आवश्यकता है, फ़ाइल (किया गया) निकालें और लाइन नंबर (असफल) निकालें।
मैं निश्चित रूप से readelf
पर कॉल कर सकता हूं और आउटपुट पार्स कर सकता हूं, लेकिन यह वास्तव में उपयुक्त नहीं है, क्योंकि आउटपुट वास्तव में क्या हुआ इसके आधार पर प्रतीक से प्रतीक तक भिन्न होता है। कभी कभी एक प्रतीक का पता एक पंक्ति और लाइन अगली पंक्ति में ऑफसेट के बारे में जानकारी में है ...
सारांश में:
वहाँ एक की सटीक लाइन नंबर प्राप्त करने के लिए एक सुंदर तरीका है रनटाइम के दौरान कार्यक्रम के भीतर से बैकट्रैक में फ़ंक्शन कॉल?
संपादित करें: उदाहरण कोड:
#define UNW_LOCAL_ONLY
#include <libunwind.h>
#include <execinfo.h>
#include <iostream>
#include <stdlib.h>
void show_backtrace()
{
// get current address
void* p = __builtin_return_address(0);
std::cout << std::hex << p << std::endl;
// get callee addresses
p = __builtin_return_address(1);
std::cout << std::hex << p << std::endl;
p = __builtin_return_address(2);
std::cout << std::hex << p << std::endl;
}
void show_backtrace2()
{
void *array[10];
size_t size;
char **strings;
int i;
size = backtrace (array, 10);
strings = backtrace_symbols ((void *const *)array, size);
for (i = 0; i < size; i++)
{
std::cout << strings[i] << std::endl;
}
free (strings);
}
void show_backtrace3 (void)
{
char name[256];
unw_cursor_t cursor; unw_context_t uc;
unw_word_t ip, sp, offp;
unw_getcontext (&uc);
unw_init_local (&cursor, &uc);
while (unw_step(&cursor) > 0)
{
char file[256];
int line = 0;
name[0] = '\0';
unw_get_proc_name (&cursor, name, 256, &offp);
unw_get_reg (&cursor, UNW_REG_IP, &ip);
unw_get_reg (&cursor, UNW_REG_SP, &sp);
std::cout << std:: hex << name << " ip = " << (long) ip
<< " , sp = " << (long) sp << std::endl;
}
}
void dummy_function2()
{
show_backtrace();
show_backtrace2();
show_backtrace3();
}
void dummy_function1()
{
dummy_function2();
} // line 73
int main(int argc, char **argv)
{
dummy_function1();
return 0;
}
संकलन और चलाएँ:
g++ test_unwind.cc -g -O0 -lunwind && ./a.out
उत्पादन:
0x400edb
0x400ef0
0x400f06
./a.out() [0x400cfb]
./a.out() [0x400ee0]
./a.out() [0x400ef0]
./a.out() [0x400f06]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed) [0x7f2f044ae76d]
./a.out() [0x400b79]
_Z15dummy_function2v ip = 400ee5 , sp = 7fffdb564580
_Z15dummy_function1v ip = 400ef0 , sp = 7fffdb564590
main ip = 400f06 , sp = 7fffdb5645a0
__libc_start_main ip = 7f2f044ae76d , sp = 7fffdb5645c0
_start ip = 400b79 , sp = 7fffdb564680
परीक्षण उदा addr2line पैदावार
/path/to/code/test_unwind.cc:73
जो सही फ़ाइल है, लेकिन गलत लाइन संख्या के साथ 0x400ef0। वास्तविक जीवन अनुप्रयोगों में लाइन संख्या कई पंक्तियों, आगे और पीछे से भिन्न हो सकती है।
संपादित करें:-S
साथ संकलन से पता चलता है कि प्रासंगिक हिस्सा है: के रूप में call
के बाद लाइन में दिखाया गया
.LCFI34:
.cfi_def_cfa_register 6
.loc 2 72 0
call _Z15dummy_function2v
.loc 2 73 0
popq %rbp
क्या addr2line
द्वारा प्रदर्शित और एक जैसे है, वापसी पता है। मैं "एंट्री" लाइन प्राप्त करना चाहता हूं, यानी पहले क्या दिखाया गया है!
क्या ऑप्टिमाइज़ेशन के बिना संकलित होने पर यह गलत हो जाता है? – Flexo
हां इसका उल्लेख करना भूल गया ... मैं – steffen
पोस्ट संपादित करूँगा निष्पादन योग्य 'gdb'' का प्रयास करें और 'l * 0x
' का उपयोग करें। क्या यह सही पता देता है, या यह 'addr2line' के समान भी देता है? – Shahbaz