5

ऐसा लगता है कि विस्टा/विंडोज सर्वर 2008 में गंभीर वर्गों का उपयोग करके ओएस की ओर जाता है जो ओएस को पूरी तरह से प्राप्त नहीं करता है। हमें यह समस्या डेल्फी एप्लिकेशन के साथ मिली और यह स्पष्ट रूप से सीएस एपीआई का उपयोग करने के कारण है। (यह SO question देखें)विवेकपूर्ण अनुभाग Vista/Win2008 पर स्मृति लीक कर रहे हैं?

क्या किसी और ने इसे अन्य भाषाओं (सी ++, ...) के साथ विकसित अनुप्रयोगों के साथ देखा है?

नमूना कोड बस 10000000 सीएस शुरू कर रहा था, फिर उन्हें हटा रहा था। यह XP/Win2003 में ठीक काम करता है लेकिन एप्लिकेशन समाप्त होने तक Vista/Win2008 में सभी शीर्ष स्मृति को रिलीज़ नहीं करता है।
जितना अधिक आप सीएस का उपयोग करते हैं, उतना ही आपका एप्लिकेशन कुछ भी नहीं के लिए स्मृति बनाए रखता है।

+0

हाय, फ्रैंकोइस। क्या आपके पास इस मुद्दे पर कोई खबर है? मैं उत्सुक हूँ :) – Alex

+0

मेरा खुद का जवाब देखें। वास्तव में एक बदलाव था, "यह एक-फीचर-ए-ए-बग" श्रेणी में .... –

+0

हाय, फ्रैंकोइस। साझा करने के लिए धन्यवाद। बीटीडब्ल्यू, आप अपना जवाब स्वीकार कर सकते हैं;) – Alex

उत्तर

7

माइक्रोसॉफ्ट वास्तव में, Vista पर InitializeCriticalSection काम करता है जिस तरह से बदल दिया है विंडोज सर्वर 2008, और शायद यह भी विंडोज 7
वे एक "सुविधा" कुछ जब आप सीएस का एक समूह का आवंटन डिबग जानकारी के लिए इस्तेमाल किया स्मृति को बनाए रखने के लिए जोड़ा। जितना अधिक आप आवंटित करेंगे, उतनी ही स्मृति बरकरार रहेगी। यह असीमित हो सकता है और अंततः बाहर निकलता है (पूरी तरह से इसे खरीदा नहीं जाता है)।
इस "फीचर" से बचने के लिए, आपको नए एपीआई InitalizeCriticalSectionEx का उपयोग करना होगा और ध्वज CRITICAL_SECTION_NO_DEBUG_INFO पास करना होगा।
इसका लाभ यह है कि यह तेजी से हो सकता है, अक्सर, केवल स्पिनकाउंट का उपयोग वास्तव में प्रतीक्षा किए बिना किया जाएगा।
नुकसान यह है कि आपके पुराने एप्लिकेशन असंगत हो सकते हैं, आपको अपना कोड बदलना होगा और अब यह प्लेटफार्म निर्भर है (आपको यह निर्धारित करने के लिए संस्करण की जांच करनी है कि कौन सा उपयोग करना है)। और यदि आपको आवश्यकता हो तो आप डीबग करने की क्षमता खो देते हैं। एक विंडोज सर्वर 2008 फ्रीज करने

टेस्ट किट:
- CSTest.exe

#include "stdafx.h" 
#include "windows.h" 
#include <iostream> 

using namespace std; 

void TestCriticalSections() 
{ 
    const unsigned int CS_MAX = 5000000; 
    CRITICAL_SECTION* csArray = new CRITICAL_SECTION[CS_MAX]; 

    for (unsigned int i = 0; i < CS_MAX; ++i) 
    InitializeCriticalSection(&csArray[i]); 

    for (unsigned int i = 0; i < CS_MAX; ++i) 
    EnterCriticalSection(&csArray[i]); 

    for (unsigned int i = 0; i < CS_MAX; ++i) 
    LeaveCriticalSection(&csArray[i]); 

    for (unsigned int i = 0; i < CS_MAX; ++i) 
    DeleteCriticalSection(&csArray[i]); 

    delete [] csArray; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    TestCriticalSections(); 

    cout << "just hanging around..."; 
    cin.get(); 

    return 0; 
} 

के रूप में इस सी ++ उदाहरण निर्माण -... इस बैच फ़ाइल चलाएं (नींद की जरूरत है।सर्वर एसडीके से exe)

@rem you may adapt the sleep delay depending on speed and # of CPUs 
@rem sleep 2 on a duo-core 4GB. sleep 1 on a 4CPU 8GB. 

@for /L %%i in (1,1,300) do @echo %%i & @start /min CSTest.exe & @sleep 1 
@echo still alive? 
@pause 
@taskkill /im cstest.* /f 

-... और शुरू की 300 उदाहरणों तक पहुँचने से पहले 8GB और ट्रैक्टर सीपीयू कोर ठंड के साथ एक Win2008 सर्वर देखते हैं।
-... विंडोज 2003 सर्वर पर दोहराएं और इसे एक आकर्षण की तरह संभालें।

+0

हाय फ्रेंकोइस, जानकारी के लिए धन्यवाद। क्या आप Vista/Windows2008 पर चलते समय स्वचालित रूप से InitializeCriticalSectionEx का उपयोग करने के लिए अपने डेल्फी 'प्रारंभिकरण'-सेक्शन कोड को पेस्ट कर सकते हैं? – carlmon

1

आप कुछ और देख रहे हैं।

मैंने अभी बनाया & इस परीक्षण कोड को चलाया। प्रत्येक मेमोरी उपयोग स्टेट स्थिर है - निजी बाइट्स, काम करने वाला सेट, प्रतिबद्धता, आदि।

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    while (true) 
    { 
     CRITICAL_SECTION* cs = new CRITICAL_SECTION[1000000]; 
     for (int i = 0; i < 1000000; i++) InitializeCriticalSection(&cs[i]); 
     for (int i = 0; i < 1000000; i++) DeleteCriticalSection(&cs[i]); 
     delete [] cs; 
    } 

    return 0; 
} 
+0

धन्यवाद माइकल। जब आपने सीएस परीक्षण चलाते समय शुरू किया और निष्क्रिय किया, तो आपके एप्लिकेशन के लिए स्मृति की निगरानी की, और, इसे करने के बाद, निष्क्रिय और अभी भी समाप्त नहीं हुआ। ऐप समाप्त होने के बाद मेमोरी हमेशा पूरी तरह से ठीक हो जाती है, समस्या तब होती है जब सीएस का उपयोग करने के बाद भी यह सक्रिय होता है। (उम्मीद है कि यह स्पष्ट है) –

+0

अनंत लूप नोट करें (जबकि (सत्य))। मैंने निगरानी की, जबकि एप्लिकेशन सक्रिय रूप से महत्वपूर्ण वर्गों को बनाने और हटाने को चला रहा था। अपेक्षित के रूप में मेमोरी उपयोग निरंतर था। – Michael

+0

मैं प्रोजेक्ट एक्सप्लोरर (निजी बाइट्स) में अच्छे दांत दिखाते हुए अपने महत्वपूर्ण अनुभागों को बनाते और हटाते समय इसे ऊपर और नीचे जाने की उम्मीद करता हूं। बीटीडब्ल्यू मैंने 10,000,000 के साथ ऐसा किया अगर इससे कोई फर्क पड़ता है। –

2

आपका परीक्षण शायद समस्या का प्रतिनिधि नहीं है। गंभीर वर्गों को "हल्के म्यूटेक्स" माना जाता है क्योंकि जब आप महत्वपूर्ण अनुभाग को प्रारंभ करते हैं तो वास्तविक कर्नेल म्यूटेक्स नहीं बनाया जाता है। इसका मतलब है कि आपके 10 एम महत्वपूर्ण वर्ग केवल कुछ सरल सदस्यों के साथ structs हैं। हालांकि, जब दो धागे एक ही समय में एक सीएस तक पहुंचते हैं, तो उन्हें सिंक्रनाइज़ करने के लिए वास्तव में एक म्यूटेक्स बनाया जाता है - और यह एक अलग कहानी है।

मुझे लगता है कि आपके असली ऐप थ्रेड्स आपके टेस्ट ऐप के विपरीत टकराते हैं। अब, यदि आप वास्तव में हल्के म्यूटेक्स के रूप में महत्वपूर्ण वर्गों का इलाज कर रहे हैं और उनमें से बहुत से बनाते हैं, तो आपका ऐप वास्तविक कर्नेल म्यूटेक्स की एक बड़ी संख्या आवंटित कर सकता है, जो प्रकाश महत्वपूर्ण अनुभाग ऑब्जेक्ट से अधिक भारी है। और चूंकि म्यूटेक्स कर्नेल ऑब्जेक्ट हैं, इसलिए उनमें से अत्यधिक संख्या बनाने से ओएस को वास्तव में चोट पहुंच सकती है।

यदि यह वास्तव में मामला है, तो आपको महत्वपूर्ण वर्गों के उपयोग को कम करना चाहिए जहां आप कई टकराव की उम्मीद करते हैं। इसका विंडोज संस्करण से कोई लेना देना नहीं है, इसलिए मेरा अनुमान गलत हो सकता है, लेकिन यह अभी भी कुछ विचार करने के लिए है। ओएस हैंडल गिनती की निगरानी करने का प्रयास करें, और देखें कि आपका ऐप कैसा चल रहा है।

+0

मुख्य बिंदु यह है कि एक ही कोड (केवल एपीआई को कॉल करना) XP/2003 पर अच्छा काम करता है लेकिन Vista/2008 पर नहीं। –

+0

मुझे नहीं पता कि आपका कोड कैसे काम करता है, लेकिन कम से कम एक टेस्ट ऐप के लिए जो दोबारा आवंटित करता है और स्मृति को मुक्त करता है, यह संभव है कि मेमोरी मैनेजर ओएस को वापस करने के बजाए मुफ्त मेमोरी कैश करने की कोशिश कर रहा है, मान लीजिए कि इसकी आवश्यकता होगी शीघ्र। विस्टा और एक्सपी में शायद अलग-अलग मेमोरी मैनेजर हैं, इसलिए अंतर। क्या ऐसा ही होता है जब वास्तविक सीएस के बजाए एक ही आकार के साथ कुछ अन्य मनमानी संरचना आवंटित होती है? क्या आप वास्तव में बहुत सारे हैंडल बनाए जा रहे हैं? – eran

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