सबसे पहले, मुझे लगता है कि यह एक पूर्ण प्रश्न के साथ एक सही प्रश्नोत्तर शैली सवाल नहीं है, लेकिन मैं इसे बेहतर बनाने के लिए किसी भी शब्द के बारे में नहीं सोच सकता। मुझे नहीं लगता कि इसका कोई पूर्ण समाधान है और यही एक कारण है कि मैं इसे स्टैक ओवरफ्लो के बजाय यहां पोस्ट कर रहा हूं।
पिछले महीने मैं सर्वर कोड (mmorpg) के एक काफी पुराने टुकड़े को फिर से लिखना शुरू कर रहा हूं, जो आधुनिक / विस्तारित / आधुनिक होने के लिए आसान है। मैंने नेटवर्क भाग के साथ शुरुआत की और मेरे लिए सामान को संभालने के लिए एक 3 पार्टी लाइब्रेरी (लीबवेंट) लागू किया। सभी री-फैक्टरिंग और कोड परिवर्तनों के साथ मैंने कहीं न कहीं स्मृति भ्रष्टाचार की शुरुआत की और मैं यह पता लगाने के लिए संघर्ष कर रहा हूं कि ऐसा कहां होता है।
मैं अपने देव / परीक्षण वातावरण पर इसे मज़बूती से पुन: पेश नहीं कर सकता, यहां तक कि जब कुछ लोड को अनुकरण करने के लिए आदिम बॉट्स को लागू करने से मुझे कोई भी दुर्घटना नहीं होती है (मैंने एक कामचलाऊ मुद्दा तय किया जो कुछ सामान का कारण बनता है)
मैंने अब तक कोशिश की है:
इससे बाहर नरक को स्वीकार करते हुए - कोई भी अमान्य नहीं लिखता जब तक कि दुर्घटनाग्रस्त न हो जाए (जो उत्पादन में 1+ दिन ले सकता है .. या सिर्फ एक घंटा) जो वास्तव में मुझे चकित कर रहा है, निश्चित रूप से कुछ बिंदु पर यह अमान्य मेमोरी तक पहुंच जाएगा और इसके द्वारा सामान को अधिलेखित नहीं करेगा मोका? (क्या पता सीमा "फैलाने" का कोई तरीका है?)
कोड-विश्लेषण उपकरण, अर्थात् आवरण और कैपचेक। हालांकि उन्होंने कुछ ओर इशारा किया था .. कोड में कुछ नस्टनेस और एज के मामले गंभीर नहीं थे।
जब तक यह gdb (undodb के माध्यम से) के साथ क्रैश नहीं हो जाता है तब तक प्रक्रिया को रिकॉर्ड करना और फिर पीछे की ओर मेरा काम करना। यह / लगता है / जैसे यह संभव होना चाहिए, लेकिन मैं या तो ऑटो-पूर्ण सुविधा का उपयोग करके क्रैशिंग जीडीबी को समाप्त करता हूं या मैं कुछ आंतरिक परिवाद संरचना में समाप्त होता हूं जहां मैं खो जाता हूं क्योंकि बहुत अधिक संभावित शाखाएं हैं (एक भ्रष्टाचार एक और कारण बनता है) पर)। मुझे लगता है कि यह अच्छा होगा यदि मैं देख सकता हूं कि एक सूचक मूल रूप से क्या है / जहां इसे आवंटित किया गया था, जो कि अधिकांश शाखाओं-मुद्दों को समाप्त कर देगा। हालांकि, मैं undodb के साथ वेलग्रिंड नहीं चला सकता, और मैं सामान्य gdb रिकॉर्ड असामान्य रूप से धीमा है (यदि वह भी वेलग्रिंड के संयोजन में काम करता है)।
को़ड समीक्षा! अपने आप से (पूरी तरह से) और कुछ दोस्तों ने मेरे कोड को देखा, हालांकि मुझे संदेह है कि यह पूरी तरह से पर्याप्त था। मैं शायद कुछ कोड की समीक्षा / मेरे साथ डिबगिंग करने के लिए एक देवता को नियुक्त करने के बारे में सोच रहा था, लेकिन मैं इसमें बहुत अधिक पैसा लगाने का जोखिम नहीं उठा सकता हूं और मुझे नहीं पता होगा कि किसी ऐसे व्यक्ति की तलाश कैसे की जाए जो थोड़ा काम करने के लिए तैयार हो। अगर वह इस मुद्दे या किसी को भी योग्य नहीं पाता है तो कोई पैसा नहीं।
मुझे यह भी ध्यान देना चाहिए: मुझे आमतौर पर लगातार अंतराल मिलते हैं। कुछ स्थान ऐसे हैं जहां दुर्घटना होती है, ज्यादातर सॉकेट क्लास से संबंधित होते हैं जो किसी तरह भ्रष्ट हो जाते हैं। क्या यह एक अमान्य सूचक है जो किसी सॉकेट या सॉकेट क्लास को स्वयं अधिलेखित नहीं किया जा रहा है (आंशिक रूप से?) अस्पष्ट के साथ इंगित करता है। हालांकि मुझे संदेह है कि यह सबसे अधिक दुर्घटनाग्रस्त है क्योंकि यह सबसे अधिक उपयोग किए जाने वाले भागों में से एक है, इसलिए यह पहली दूषित स्मृति है जिसका उपयोग किया जाता है।
इन सभी मुद्दों ने मुझे लगभग 2 महीने (चालू और बंद, एक शौक परियोजना के अधिक) में व्यस्त कर दिया है और वास्तव में मुझे उस बिंदु पर निराश कर रहा है जहां मैं क्रोधी IRL बन जाता हूं और बस देने के बारे में सोचता हूं। मैं सिर्फ इस बारे में नहीं सोच सकता कि मुझे इस मुद्दे को खोजने के लिए क्या करना चाहिए।
क्या कोई उपयोगी तकनीक है जो मुझे याद है? आप इससे कैसे निपटते हैं? (यह सामान्य नहीं हो सकता है क्योंकि इस बारे में ज्यादा जानकारी नहीं है .. या मैं वास्तव में अंधा हूं?)
संपादित करें:
मामले में कुछ चश्मा यह मायने रखता है:
Gcc 4.7 के माध्यम से c ++ (11) का उपयोग करना (डेबियन व्हीज़ी द्वारा दिया गया संस्करण)
कोडबेस 150k लाइनों के आसपास है
David.pfx पोस्ट के जवाब में संपादित करें: (धीमी प्रतिक्रिया के लिए खेद है)
क्या आप पैटर्न को देखने के लिए क्रैश का सावधानीपूर्वक रिकॉर्ड रख रहे हैं?
हां, मेरे पास अभी भी हाल ही में हुए क्रैश के डंप हैं
क्या कुछ जगहें वास्तव में समान हैं? किस तरह से?
खैर, सबसे हालिया संस्करण में (वे जब भी मैं कोड जोड़ / हटाकर संबंधित संरचनाएँ बदलता हूँ, तो यह बदल जाता है) यह हमेशा एक आइटम टाइमर विधि में पकड़ा जाएगा। मूल रूप से किसी आइटम का एक विशिष्ट समय होता है जिसके बाद वह समाप्त हो जाता है और यह ग्राहक को अद्यतन जानकारी भेजता है। अमान्य सॉकेट पॉइंटर में होगा (अभी भी मान्य है जहाँ तक मैं बता सकता हूँ) खिलाड़ी वर्ग, ज्यादातर उसी से संबंधित है। मैं भी सफाई के चरण में दुर्घटनाओं के भार का सामना कर रहा हूं, सामान्य बंद के बाद जहां यह सभी स्थिर वर्गों को नष्ट कर रहा है जो स्पष्ट रूप से नष्ट नहीं किया गया है ( __run_exit_handlers
बैकट्रेस में)। ज्यादातर std::map
एक वर्ग से जुड़े होते हैं , यह अनुमान लगाते हुए कि यह पहली बात है जो हालांकि सामने आती है।
भ्रष्ट डेटा कैसा दिखता है? शून्य? Ascii? पैटर्न?
मुझे अभी तक कोई पैटर्न नहीं मिला है, मुझे कुछ यादृच्छिक लगता है। यह बताना मुश्किल है क्योंकि मुझे नहीं पता कि भ्रष्टाचार कहां शुरू हुआ।
क्या यह ढेर से संबंधित है?
यह पूरी तरह से हीप से संबंधित है (मैंने जीसीसी के स्टैक गार्ड को सक्षम किया और वह कुछ भी पकड़ नहीं पाया)।
क्या भ्रष्टाचार एक के बाद होता है
free()
?
आप उस एक पर थोड़ा विस्तार करने जा रहे हैं। क्या आपका मतलब है कि पहले से ही खाली पड़ी वस्तुओं के संकेत होने चाहिए? जब वस्तु नष्ट हो जाती है, तो मैं प्रत्येक संदर्भ को शून्य करने के लिए सेट कर रहा हूं, इसलिए जब तक कि मैं कहीं चूक न जाए, नहीं। हालांकि यह मान्य नहीं था, लेकिन इसे वैग्राइंड में दिखाना चाहिए।
क्या नेटवर्क ट्रैफ़िक (बफर साइज़, रिकवरी साइकल) के बारे में कुछ विशिष्ट है?
नेटवर्क ट्रैफ़िक में कच्चे डेटा होते हैं। तो चार सरणियों, (यू) intX_t या पैक (पैडिंग को हटाने के लिए) अधिक जटिल चीजों के लिए संरचना, प्रत्येक पैकेट में एक हेडर होता है जिसमें एक आईडी और पैकेट आकार होता है जो कि अपेक्षित आकार के विरुद्ध मान्य होता है। वे कुछ एमबी के आकार वाले सबसे बड़े (आंतरिक 'बूटअप' पैकेट, स्टार्टअप पर एक बार निकाल दिए गए) के आसपास 10-60bytes हैं।
बहुत सारे और उत्पादन जोर देता है। क्षति का प्रचार करने से पहले जल्दी और अनुमानित रूप से क्रैश करें।
मेरे पास एक बार std::map
भ्रष्टाचार से संबंधित एक दुर्घटना थी , प्रत्येक इकाई के पास "दृश्य" का एक नक्शा है, प्रत्येक इकाई जो इसे देख सकती है और इसके विपरीत है। मैंने सामने और बाद में एक 200byte बफर जोड़ा, इसे 0x33 से भरा और प्रत्येक एक्सेस से पहले इसे चेक किया। भ्रष्टाचार सिर्फ जादुई रूप से गायब हो गया, मुझे कुछ ऐसा करना चाहिए जिसके बारे में कुछ और भ्रष्ट हो।
स्ट्रेटेजिक लॉगिंग, ताकि आप सही तरीके से जान सकें कि पहले क्या हो रहा था। जैसे ही आप उत्तर के करीब आते हैं, लॉगिंग में जोड़ें।
यह काम करता है .. एक विस्तार के लिए।
हताशा में, क्या आप राज्य और ऑटो-पुनरारंभ को बचा सकते हैं? मैं उत्पादन सॉफ्टवेयर के कुछ टुकड़ों के बारे में सोच सकता हूं जो ऐसा करते हैं।
मैं कुछ ऐसा करता हूं। सॉफ्टवेयर में एक मुख्य "कैश" प्रक्रिया और कुछ अन्य कार्यकर्ता होते हैं जो सभी सामान प्राप्त करने और सहेजने के लिए कैश का उपयोग करते हैं। इसलिए प्रति दुर्घटना मैं बहुत प्रगति नहीं खोता, यह अभी भी सभी उपयोगकर्ताओं और इतने पर डिस्कनेक्ट करता है, यह निश्चित रूप से एक समाधान नहीं है।
Concurrency: सूत्रण, दौड़ की स्थिति, आदि
"Async" क्वेरी करने के लिए एक mysql थ्रेड है, हालांकि यह सभी अछूता है और सभी लॉक के साथ फ़ंक्शन के माध्यम से केवल डेटाबेस वर्ग को जानकारी साझा करता है।
बीच में आता है
इसमें एक अवरोध टाइमर है जो इसे लॉक करने से रोकता है, बस गर्भपात करता है यदि यह 30 सेकंड के लिए एक चक्र पूरा नहीं करता है, तो यह कोड सुरक्षित होना चाहिए:
if (!tics) {
abort();
} else
tics = 0;
टिक्स वह है volatile int tics = 0;
जो हर बार एक चक्र पूरा होने पर बढ़ाया जाता है। पुराना कोड भी।
घटनाओं / कॉलबैक / अपवाद: राज्य को भ्रष्ट करना या अप्रत्याशित रूप से ढेर करना
बहुत सारे कॉलबैक का उपयोग किया जा रहा है (async नेटवर्क I / O, टाइमर), लेकिन उन्हें कुछ भी बुरा नहीं करना चाहिए।
असामान्य डेटा: असामान्य इनपुट डेटा / समय / स्थिति
मेरे पास इससे संबंधित कुछ मामले हैं। पैकेट को संसाधित करते समय एक सॉकेट को डिस्कनेक्ट करने के परिणामस्वरूप अभी भी एक नलप्रॉप्ट और इस तरह से एक्सेस किया जा सकता है, लेकिन उन लोगों को अभी तक स्पॉट करना आसान है, क्योंकि हर संदर्भ को कक्षा को स्वयं करने के बाद सही तरीके से साफ हो जाता है। (विनाश खुद को नष्ट कर दिया जाता है एक चक्र से सभी नष्ट वस्तुओं को हटाकर)
एक अतुल्यकालिक बाहरी प्रक्रिया पर निर्भरता।
विस्तृत करने के लिए परवाह? यह कुछ हद तक, ऊपर उल्लिखित कैश प्रक्रिया है। केवल एक चीज जिसकी मैं कल्पना कर सकता हूं, वह यह है कि मेरे सिर के ऊपर से यह जल्दी खत्म नहीं होगा और कचरा डेटा का उपयोग नहीं किया जाएगा, लेकिन ऐसा नहीं है क्योंकि यह नेटवर्क का भी उपयोग कर रहा है। एक ही पैकेट मॉडल।
/analyze
) और Apple के मॉलोक और स्क्रिबल गार्ड को भी जोड़ें। आपको यथासंभव अधिक से अधिक मानकों का उपयोग करके यथासंभव संकलक का उपयोग करना चाहिए क्योंकि संकलक चेतावनी एक निदान है और वे समय के साथ बेहतर हो जाते हैं। कोई चांदी की गोली नहीं है, और एक आकार सभी फिट नहीं है। जितने अधिक उपकरण और कंपाइलर आप उपयोग करते हैं, उतना ही अधिक कवरेज पूरा होता है क्योंकि प्रत्येक उपकरण की ताकत और कमजोरियां होती हैं।