2011-09-16 7 views
8

libdispatch, queue.h के लिए ऐप्पल की शीर्षलेख फ़ाइलों में से एक में, निम्न चेतावनी प्रकट होती है:सी डब्ल्यू/ब्लॉक: ढेर से बाहर निकलने वाले स्टैक-आधारित ब्लॉक

// The declaration of a block allocates storage on the stack. 
// Therefore, this is an invalid construct: 

dispatch_block_t block; 

if (x) { 
    block = ^{ printf("true\n"); }; 
} else { 
    block = ^{ printf("false\n"); }; 
} 
block(); // unsafe!!! 

// What is happening behind the scenes: 

if (x) { 
    struct Block __tmp_1 = ...; // setup details 
    block = &__tmp_1; 
} else { 
    struct Block __tmp_2 = ...; // setup details 
    block = &__tmp_2; 
} 

// As the example demonstrates, the address of a stack variable is 
// escaping the scope in which it is allocated. That is a classic C bug. 

जितना मैं कर सकता हूं, मैं इस परीक्षण की अनुमति नहीं दे सकता जो इस बग का उदाहरण देता है। मैं ब्लॉक बना सकता हूं जो ढेर पर तत्काल होते हैं, लेकिन वे (प्रतीत होते हैं) हमेशा एक दूसरे के संबंध में दायरे से बाहर होने पर, स्टैक पर अद्वितीय पते पर दिखाई देते हैं।

मुझे कल्पना है कि इसका उत्तर सरल है, लेकिन यह मुझसे बच निकला है। क्या कोई मेरी (सीमित) समझ में अंतर को भर सकता है?

संपादित करें: मैंने this प्रतिक्रिया देखी है, लेकिन मुझे समझ में नहीं आता कि यह उदाहरण ऊपर दिए गए मेरे उदाहरण में अनुवाद कैसे कर सकता है। क्या कोई मुझे if संरचनाओं का उपयोग करके एक उदाहरण दिखा सकता है?

+0

आपके द्वारा पोस्ट किए गए लिंक को एक अलग समस्या के साथ करना है, अर्थात्, बंद होने से परिवर्तनीय चर की उपस्थिति में अजीब कार्य करना प्रतीत होता है। प्रश्न देखें ["जावास्क्रिप्ट: लूप बंद करें?"] (Http://stackoverflow.com/questions/5555464/javascript-closure-of-loop), जो जावास्क्रिप्ट में एक ही समस्या है। हालांकि, ऐसा लगता है कि उन्होंने इस टिप्पणी के खिलाफ गलती की चेतावनी दी है। क्या ब्लॉक इन दिनों स्वचालित रूप से प्रतिलिपि बनाते हैं? मैं भी जानना चाहता हूं। –

+0

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

उत्तर

5

एक समारोह के अंदर एक ढेर बंद दुर्घटना करने के लिए:

  • आप यह सुनिश्चित करें कि बंद वास्तव में एक ढेर बंद है बनाने की जरूरत है। ऐप्पल क्लैंग 2.1 के रूप में, एक बंद जो वर्तमान संदर्भ में चर का संदर्भ नहीं देता है (जैसे queue.h में से एक) को वैश्विक बंद होने के रूप में महसूस किया जाता है। यह एक कार्यान्वयन विवरण है जो विभिन्न कंपेलरों/कंपाइलर संस्करणों के बीच भिन्न हो सकता है;

  • कंपाइलर को उस कोड को उत्सर्जित करना होगा जो स्टैक क्षेत्र को प्रभावी ढंग से पुन: उपयोग/पुनः लिखता है जहां एक बार बंद रहता है। अन्यथा, उस फ़ंक्शन के अंदर मौजूद प्रत्येक ऑब्जेक्ट फ़ंक्शन स्टैक फ्रेम में एक अलग पते में रहता है, जिसका अर्थ है कि आपको उस फ़ंक्शन के अंदर कोई क्रैश नहीं मिलेगा। ऐसा लगता है कि ऐप्पल क्लैंग 2.1 स्टैक मेमोरी पतों का पुन: उपयोग नहीं करता है। जीसीसी 4.6 उनका पुन: उपयोग कर सकता है, लेकिन यह बंद करने का समर्थन नहीं करता है।

के बाद से एप्पल बजना 2.1 एक समारोह स्टैक फ्रेम में पते का पुन: उपयोग नहीं करता है और जीसीसी 4.6 बंद का समर्थन नहीं करता है, क्या मैं इसे बता सकते हैं इस विशिष्ट उदाहरण बनाने के लिए संभव नहीं है से - एक समारोह के अंदर, एक आह्वान गुंजाइश ढेर बंद - दुर्घटना से बाहर।

मैंने my blog पर इसके बारे में एक और विस्तृत पाठ लिखा।

+0

प्रतिक्रिया के लिए धन्यवाद, Bavarious। आप उन लोगों में से एक थे जिन्हें मैंने आशा की थी कि मेरी क्वेरी का जवाब होगा। :) मुझे एहसास हुआ था कि ब्लॉक को राज्य पर कब्जा करना होगा (अन्यथा उन्हें वैश्विक रूप से प्रस्तुत किया जाता है) को ढेर पर रखा जाना चाहिए, लेकिन मुझे आपके जैसा ही मिला - स्टैक पते को बंद करने के लिए पुन: उपयोग नहीं किया जाता है। –

+0

@Sed यह अधिक सामान्य है - ढेर पते स्पष्ट रूप से किसी भी प्रकार की वस्तु के लिए पुन: उपयोग नहीं किए जाते हैं, बंद किए गए बंद होते हैं। इसका प्रभावी अर्थ यह है कि फ़ंक्शन स्टैक फ्रेम में जो कुछ भी बनाया गया है वह फ़ंक्शन के अंत तक जीवित है। मुझे यकीन नहीं है कि क्लैंग जानबूझकर उस से बचाता है या भविष्य में इसे लागू किया जा सकता है या नहीं। –

+0

मैं "आह!" के साथ पालन करने की योजना बना रहा था, यह पाया गया कि स्टैक पते का वास्तव में 'लंबे प्रकार के प्रकारों' के लिए पुन: उपयोग किया जा रहा था, लेकिन मेरे पास मेरा संकलक जीसीसी 4.2 पर सेट किया गया था। डी 'ओह। –

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