2012-08-27 16 views
18

में स्टैक ओवरफ़्लो को कैसे संभालें या इससे बचें C++ में एक स्टैक ओवरफ़्लो आमतौर पर प्रोग्राम का एक अप्राप्य क्रैश होता है। उन कार्यक्रमों के लिए जो वास्तव में मजबूत होने की आवश्यकता है, यह एक अस्वीकार्य व्यवहार है, विशेष रूप से क्योंकि स्टैक आकार सीमित है। समस्या को संभालने के तरीके के बारे में कुछ सवाल।सी ++

  1. वहाँ एक सामान्य तकनीक से ढेर अतिप्रवाह को रोकने के लिए एक रास्ता है। (ए स्केलेबल, मजबूत समाधान, कि, आदि ढेर का एक बहुत खा बाहरी पुस्तकालयों के साथ काम भी शामिल है)

  2. वहाँ एक रास्ता मामले वे होते हैं ढेर अतिप्रवाह को संभालने के लिए है? अधिमानतः, उस तरह के मुद्दे से निपटने के लिए एक हैंडलर होने तक ढेर अवांछित हो जाता है।

  3. वहां ऐसी भाषाएं हैं, जिनमें विस्तारणीय ढेर वाले धागे हैं। क्या सी ++ में ऐसा कुछ संभव है?

सी ++ व्यवहार के समाधान पर किसी भी अन्य सहायक टिप्पणियों की सराहना की जाएगी।

+4

http://support.microsoft.com/kb/315937 –

+1

मानक भी ढेर उल्लेख नहीं है, आप जो मंच आप लक्षित कर रहे निर्दिष्ट करना चाहिए; कई प्लेटफार्म स्टैक ओवरफ्लो को रोकने या यहां तक ​​कि "स्टैक ओवरफ्लो अलर्ट" प्राप्त करने के साधन प्रदान करते हैं, जब स्टैक लगभग समाप्त हो जाता है। –

+5

व्यक्तिगत रूप से, मुझे लगता है कि एसओ कुछ बचने के लिए नहीं है, बल्कि गले लगाने के लिए है। बस महान समुदाय को देखो! –

उत्तर

17

एक स्टैक ओवरफ़्लो को संभालना सही समाधान नहीं है, इसके बजाय, आपको यह सुनिश्चित करना होगा कि आपका प्रोग्राम ढेर से अधिक नहीं हो।

स्टैक पर बड़े चर आवंटित न करें (जहां "बड़ा" प्रोग्राम पर निर्भर करता है)। सुनिश्चित करें कि किसी भी रिकर्सिव एल्गोरिदम ज्ञात अधिकतम गहराई के बाद समाप्त हो जाता है। यदि एक रिकर्सिव एल्गोरिदम किसी अज्ञात संख्या या बड़ी संख्या में रिकर्स कर सकता है, तो या तो अपने आप को पुनरावृत्ति का प्रबंधन करें (अपने गतिशील आवंटित स्टैक को बनाए रखने के द्वारा) या रिकर्सिव एल्गोरिदम को समकक्ष पुनरावृत्त एल्गोरिदम

एक प्रोग्राम जो आवश्यक है "वास्तव में मजबूत" तीसरे पक्ष या बाहरी पुस्तकालयों का उपयोग नहीं करेगा जो "बहुत ढेर खाते हैं।"


ध्यान दें कि कुछ प्लेटफॉर्म एक कार्यक्रम में सूचित करते हैं एक ढेर अतिप्रवाह होता है और कार्यक्रम त्रुटि को संभालने के लिए अनुमति देते हैं। विंडोज़ पर, उदाहरण के लिए, एक अपवाद फेंक दिया जाता है। यह अपवाद एक सी ++ अपवाद नहीं है, हालांकि, यह एक असीमित अपवाद है। जबकि एक सी ++ अपवाद केवल throw कथन द्वारा फेंक दिया जा सकता है, किसी प्रोग्राम के निष्पादन के दौरान किसी भी समय एक एसिंक्रोनस अपवाद फेंक दिया जा सकता है। हालांकि, इसकी अपेक्षा की जाती है, क्योंकि किसी भी समय एक स्टैक ओवरफ़्लो हो सकता है: किसी फ़ंक्शन कॉल या स्टैक आवंटन स्टैक को ओवरफ़्लो कर सकता है।

समस्या यह है कि एक स्टैक ओवरफ़्लो किसी भी अपवाद को फेंकने की उम्मीद नहीं होने वाले कोड से भी एसिंक्रोनस अपवाद को फेंक सकता है (उदा।, noexcept या throw() को C++ में चिह्नित फ़ंक्शंस से)। इसलिए, अगर आप इस अपवाद को किसी भी तरह से संभालते हैं, तो आपके पास यह जानने का कोई तरीका नहीं है कि आपका प्रोग्राम एक सुरक्षित स्थिति में है। इसलिए, एसिंक्रोनस अपवाद को संभालने का सबसे अच्छा तरीका यह है कि इसे (*) पर संभालना न पड़े। अगर किसी को फेंक दिया जाता है, तो इसका मतलब है कि कार्यक्रम में एक बग है।

अन्य प्लेटफार्मों "हैंडलिंग" एक ढेर अतिप्रवाह त्रुटि के लिए इसी तरह के तरीकों है, लेकिन किसी भी तरह के तरीकों में एक ही समस्या से ग्रस्त होने की संभावना है: कोड है कि एक त्रुटि का कारण हो सकता एक त्रुटि पैदा करने के लिए नहीं की उम्मीद है।

(*) कुछ बहुत दुर्लभ अपवाद हैं।

+0

तीसरे पक्ष के पुस्तकालयों का उपयोग अक्सर लागत का सवाल होता है। यदि आप किसी भी समय अपने प्रोग्राम में विंडोज़ पर हैं तो आपको WinApi को प्रत्यक्ष या परोक्ष रूप से उपयोग करना होगा। अन्य प्रणाली पर वही। आप बिल्कुल तीसरे पक्ष के पुस्तकालयों के बिना नहीं रह पाएंगे। (आप सी ++ मानक लाइब्रेरी को तीसरे पक्ष के रूप में मान सकते हैं।) लेकिन मेरा मुद्दा यह है कि, यदि आप एक सुपर मजबूत प्रोग्राम चाहते हैं और लागत को कम करने के लिए तीसरे पक्ष के पुस्तकालयों का उपयोग करना चाहते हैं, तो आपको यह गारंटी देने का एक तरीका चाहिए कि कार्यक्रम नहीं है अन्य पुस्तकालयों में एक ढेर ओवरफ्लो द्वारा पूरी तरह दुर्घटनाग्रस्त हो जाता है। –

0

सी ++ एक शक्तिशाली भाषा है, और उस शक्ति के साथ पैर में खुद को शूट करने की क्षमता आती है। स्टैक ओवरफ़्लो होने पर मुझे पता लगाने और सही/निरस्त करने के लिए किसी भी पोर्टेबल तंत्र से अवगत नहीं है।निश्चित रूप से ऐसा कोई भी पता कार्यान्वयन-विशिष्ट होगा। उदाहरण के लिए g ++ आपके स्टैक उपयोग की निगरानी में सहायता के लिए -fstack-protector प्रदान करता है।

सामान्य रूप से आपकी सबसे अच्छी शर्त बड़े ढेर-आधारित चर से बचने और रिकर्सिव कॉल के साथ सावधान रहने में सक्रिय होना है।

+0

'-फस्टैक-रक्षक' अतिरिक्त स्टैक आवंटन की निगरानी में मदद नहीं करता है। यह पता लगाने के लिए है कि स्टैक-आवंटित चर उनके सीमाओं के बाहर लिखते हैं। –

3

आप ढेर के खिलाफ की रक्षा कर सकते हैं अच्छा प्रोग्रामिंग प्रथाओं का उपयोग कर, की तरह overflows:

  1. प्रत्यावर्तन के साथ बहुत सावधान रहो, मैं हाल ही में देखा है एक बहुत बुरी तरह से लिखा पुनरावर्ती CreateDirectory समारोह से उत्पन्न, अगर आप यदि निश्चित नहीं हैं कि आपके कोड 100% ठीक है, फिर गार्डिंग वैरिएबल जोड़ें जो एन रिकर्सिव कॉल के बाद निष्पादन को रोक देगा। या फिर भी रिकर्सिव कार्यों को बेहतर नहीं लिखते हैं।
  2. स्टैक पर विशाल सरणी न बनाएं, यह कक्षा क्षेत्र के रूप में एक बहुत बड़ी सरणी की तरह छुपा सरणी हो सकता है। वेक्टर का उपयोग करना हमेशा बेहतर होता है।
  3. एलोका के साथ बहुत सावधान रहें, खासकर यदि इसे कुछ मैक्रो परिभाषा में रखा गया हो। मैंने स्ट्रिंग रूपांतरण मैक्रोज़ के परिणामस्वरूप कई एसओ देखा है जो तेजी से स्मृति आवंटन के लिए एलोका का उपयोग कर रहे थे।
  4. सुनिश्चित करें कि आपका स्टैक आकार इष्टतम है, यह एम्बेडेड प्लेटफ़ॉर्म में अधिक महत्वपूर्ण है। यदि आप धागे ज्यादा नहीं करते हैं, तो इसे छोटा ढेर दें, अन्यथा बड़े पैमाने पर उपयोग करें। मुझे पता है कि आरक्षण केवल कुछ पता सीमा लेना चाहिए - भौतिक स्मृति नहीं।
उन

सबसे एसओ का कारण बनता है मैं पिछले कुछ वर्षों में देखा है।

स्वत: SO खोजने के लिए आपको कुछ स्थिर कोड विश्लेषण टूल ढूंढने में सक्षम होना चाहिए।

+0

इन रचनात्मक विचारों के लिए धन्यवाद। –

0

पुन: विस्तारणीय ढेर। आप अपने आप को कुछ इस तरह से अधिक ढेर अंतरिक्ष दे सकता है:

#include <iostream> 

int main() 
{ 
    int sp=0; 

    // you probably want this a lot larger 
    int *mystack = new int[64*1024]; 
    int *top = (mystack + 64*1024); 

    // Save SP and set SP to our newly created 
    // stack frame 
    __asm__ ( 
     "mov %%esp,%%eax; mov %%ebx,%%esp": 
     "=a"(sp) 
     :"b"(top) 
     : 
     ); 
    std::cout << "sp=" << sp << std::endl; 

    // call bad code here 

    // restore old SP so we can return to OS 
    __asm__(
     "mov %%eax,%%esp": 
     : 
     "a"(sp) 
     :); 

    std::cout << "Done." << std::endl; 

    delete [] mystack; 
    return 0; 
} 

यह जीसीसी के कोडांतरक वाक्य रचना है।

+0

ओह, उस 'int * top = (mystack + 64 * 1024 - 1); ' –

+0

शायद फिर भी: पैर में खुद को शूट करने के लिए पर्याप्त शक्ति। –

+0

ओच! क्या हैक! –

-2
#include <iostream> 
using **namespace** std; 
class Complex 
{ 

public: double *re, *im; 

Complex() 
{ 

    re = new double(r); 

    im = new double(m); 

} 

Complex() 
{ 

    re = new double; 
    im = new double; 
    *re = *t.re; 
    *im= *t.im; 

} 

~Complex() 
{ 

     delete re, im; 

} 

}; 

int main() { 

double x, y, z; 
cin >> x >> y >> z; 
Complex n1(x,y); 
cout << *n1.re << "+" << *n1.im << "i "; 
Complex n2 = n1; 
cout << *n2.re << "+" << *n2.im << "i "; 
*n1.im = z; 
cout << *n2.re << "+" << *n2.im << "i "; 
cout << *n1.re << "+" << *n1.im << "i "; 
return 0; 
} 
+1

यह सवाल से कैसे संबंधित है? –