2010-01-11 14 views
9

के लिए ब्रेकपॉइंट सेट करें, मैं जीडीबी का उपयोग करके एक साधारण स्टॉप-एंड-कॉपी कचरा कलेक्टर (सी में लिखित) डीबग करने की कोशिश कर रहा हूं। जीसी सिगबस को संभालने से काम करता है। मैंने अपने सिगबस सिग्नल हैंडलर के शीर्ष पर ब्रेकपॉइंट सेट किया है। मैंने जीडीबी को अपने कार्यक्रम में सिगबस पास करने के लिए कहा है। हालांकि, यह काम नहीं करता है।जीडीबी: एक सिगबस हैंडलर

#include <stdio.h> 
#include <sys/mman.h> 
#include <assert.h> 
#include <signal.h> 

#define HEAP_SIZE 4096 

unsigned long int *heap; 

void gc(int n) { 
    signal(SIGBUS, SIG_DFL); // just for debugging 
    printf("GC TIME\n"); 
} 

int main() { 

    // Allocate twice the required heap size (two semi-spaces) 
    heap = mmap(NULL, HEAP_SIZE * 2, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, 
       -1, 0); 
    assert (heap != MAP_FAILED); 
    // 2nd semi-space is unreadable. Using "bump-pointer allocation", a SIGBUS 
    // tells us we are out of space and need to GC. 
    void *guard = mmap(heap + HEAP_SIZE, HEAP_SIZE, PROT_NONE, MAP_ANON | 
        MAP_SHARED | MAP_FIXED, -1, 0); 
    assert (guard != MAP_FAILED); 
    signal(SIGBUS, gc); 
    heap[HEAP_SIZE] = 90; // pretend we are out of heap space 
    return 0; 
} 

मैं संकलन और मैक ओएस एक्स 10.6 पर कार्यक्रम चलाने के लिए और उत्पादन मैं उम्मीद मिलती है::

$ gcc debug.c 
$ ./a.out 
GC TIME 
Bus error 

निम्नलिखित कार्यक्रम (समझाया इनलाइन) मेरी समस्या का सार से पता चलता मैं जीडीबी का उपयोग करके इस कार्यक्रम को चलाने और डीबग करना चाहता हूं। विशेष रूप से, मैं जीसी फ़ंक्शन (वास्तव में, जीसी सिग्नल हैंडलर) पर ब्रेकपॉइंट सेट करना चाहता हूं।

$ gdb ./a.out 
GNU gdb 6.3.50-20050815 (Apple version gdb-1346) (Fri Sep 18 20:40:51 UTC 2009) 
... snip ... 
(gdb) handle SIGSEGV SIGBUS nostop noprint 
Signal  Stop Print Pass to program Description 
SIGBUS  No No Yes  Bus error 
SIGSEGV  No No Yes  Segmentation fault 
(gdb) break gc 
Breakpoint 1 at 0x100000d6f 

हालांकि, हम कभी नहीं ब्रेकपाइंट तक पहुँचने: स्वाभाविक रूप से, मैं GDB बताने के लिए और साथ ही SIGBUS पर रोक नहीं की जरूरत है

(gdb) run 
Starting program: /snip/a.out 
Reading symbols for shared libraries +. done 

Program received signal EXC_BAD_ACCESS, Could not access memory. 
Reason: KERN_PROTECTION_FAILURE at address: 0x0000000100029000 
0x0000000100000e83 in main() 
(gdb) 

जाहिर है, संकेत हैंडलर लागू नहीं किया गया है (जीसी समय नहीं है मुद्रित)। इसके अलावा, हम अभी भी मुख्य() में हैं, दोषपूर्ण mov:

0x0000000100000e83 <main+247>: movq $0x5a,(%rax) 

कोई विचार?

धन्यवाद।

उत्तर

5

वही कोड (एसआईजीएसईजीवी को संभालने के लिए संशोधित) लिनक्स पर जीडीबी में अपेक्षित काम करता है; यह उस प्लेटफॉर्म पर ओएस एक्स या जीडीबी के बंदरगाह में एक बग हो सकता है।

गुगलिंग को broken OS X behavior मिल गया है, जैसे कि प्रोग्राम चलाने से पहले set inferior-bind-exception-port off एक प्रकार के वर्कअराउंड के साथ 10.1 पर वापस।

(similar bug on Windows है।)

+0

धन्यवाद, यह एक ओएस एक्स विशिष्ट बग है। कामकाज कार्यक्रम को पूरा करने के लिए चलाता है, लेकिन जीडीबी अब ब्रेकपॉइंट पर नहीं रोकता है। ओह ठीक है ... –

+0

एक समाधान के लिए मेरा जवाब देखें जो आपको हैंडलर के अंदर तोड़ने देता है। – LaC

4

के बाद for(;;); डालने के बारे में, सामान्य रूप से प्रोग्राम चलाते हुए, और फिर जीसी टाइम प्रिंट के बाद gdb के साथ प्रक्रिया से कनेक्ट करने के बारे में कैसे?

+0

अच्छा, यह काम करेगा। लेकिन, क्या एक क्लीनर समाधान नहीं है? क्या सिगबस हैंडलर में ब्रेकपॉइंट सेट करना वास्तव में संभव नहीं है? –

2

आप सिगबस पाने की अपेक्षा क्यों करते हैं? सिगबस आमतौर पर एक आर्किटेक्चर पर संरेखण त्रुटि का अर्थ है, जहां कुछ डेटाटाइप में संरेखण आवश्यकताएं होती हैं। ऐसा लगता है कि आप बस अपने आवंटित क्षेत्र के बाहर मेमोरी तक पहुंचने का प्रयास कर रहे हैं, और मुझे उम्मीद है कि आपको सिगब्स के बजाय SIGSEGV मिल जाएगा।

संपादित करें:

ऐसा लगता है कि मैं क्या SIGSEGV के रूप में के बारे में सोच के लिए मैक ओएस एक्स नाम SIGBUS है। इसलिए, इस जवाब को अनदेखा करें।

यदि यह कोई मदद है, तो ब्रेकपॉइंट अपेक्षित काम करता है (यानी यह काम करता है) जब मैं लिनक्स सिस्टम पर प्रोग्राम का प्रयास करता हूं, सिगब्स द्वारा SIGSEGV द्वारा प्रतिस्थापित किया जाता है।

संपादित करें 2:

आप अपने प्रोग्राम में भी SIGSEGV को पकड़ने की कोशिश कर सकते हैं? ऐसा लगता है कि मैक ओएस एक्स में मेमोरी मैप किए जाने पर सिग्नल का प्रकार अलग-अलग हो सकता है (मैं सिर्फ here और here पर चर्चा पढ़ता हूं), और जब आप डीबगर में चलाते हैं तो शायद एक अलग सिग्नल फेंक दिया जा सकता है?

+0

मुझे एक सिगबस की उम्मीद है क्योंकि जब मैं इसे जीडीबी के बिना चलाता हूं तो मुझे सिगबस मिलता है। जैसा कि आप सुझाव देते हैं, यह वह नहीं है जिसे मैं शुरू करने की उम्मीद करता हूं। –

5

आंतरिक रूप से, खराब मेमोरी के परिणामस्वरूप मैक अपवाद EXC_BAD_ACCESS को प्रोग्राम में भेजा जा रहा है। आम तौर पर, इसका अनुवाद सिगबस यूनिक्स सिग्नल में किया जाता है। हालांकि, जीडीबी सिग्नल अनुवाद से पहले सीधे माच अपवादों को रोकता है। समाधान आपके प्रोग्राम को चलाने से पहले gdb कमांड set dont-handle-bad-access 1 देना है। फिर सामान्य तंत्र का उपयोग किया जाता है, और आपके सिग्नल हैंडलर के अंदर ब्रेकपॉइंट्स सम्मानित होते हैं।