2012-08-09 4 views
5

मैं निम्नलिखित कोड के साथ विकलांग लाइन इनपुट की गई:स्टैक को दूषित करने वाले लूप में ReadConsole क्यों कॉल कर रहा है?

DWORD dwConsoleMode; 
GetConsoleMode(hStdIn, &dwConsoleMode); 
dwConsoleMode ^= ENABLE_LINE_INPUT; 
SetConsoleMode(hStdIn, dwConsoleMode); 

तो मैं एक पाश में ReadConsole बोल रहा हूँ ... एक पाश में:

wchar_t cBuf; 

while (1) { 
    /* Display Options */ 

    do { 
     ReadConsole(hStdIn, &cBuf, 1, &dwNumRead, NULL); 
    } while (!iswdigit(cBuf)); 

    putwchar(cBuf); 

    if (cBuf == L'0') break; 
} 

अगर मैं कार्यक्रम चलाने के लिए और प्रेस 0 अभी, यह स्पष्ट रूप से मौजूद है।
लेकिन अगर मैं चाबियों का एक गुच्छा दबाएं, फिर 0, दबाई जाने वाली प्रोग्राम मौजूद है इसके साथ दुर्घटनाओं:

रन-टाइम जांच विफलता # 2 - चर 'cBuf' चारों ओर स्टैक दूषित है।

यह ढेर भ्रष्ट क्यों हो रहा है? कोड सरल है, इसलिए मैं यह नहीं समझ सकता कि क्या गलत है।

लिटिल कार्यक्रम है कि मैं के साथ समस्या को पुन: कर सकते हैं:

#include <windows.h> 
#include <stdio.h> 

int wmain(int argc, wchar_t *argv[]) 
{ 
    DWORD dwNumRead; 
    wchar_t cBuf; 

    HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE); 

    DWORD dwConsoleMode; 
    GetConsoleMode(hStdIn, &dwConsoleMode); 
    dwConsoleMode ^= ENABLE_LINE_INPUT; 
    SetConsoleMode(hStdIn, dwConsoleMode); 

    while (true) 
    { 
     wprintf(L"\nEnter option: "); 

     do { 
      ReadConsoleW(hStdIn, &cBuf, 1, &dwNumRead, NULL); 
     } while (!iswdigit(cBuf)); 

     putwchar(cBuf); 

     if (cBuf == L'0') break; 
    } 

    return 0; 
} 

आप एक तरह से अपने कीबोर्ड मैश करने के लिए आप इसे चलाने के बाद है, तो 0 दबाते हैं, और यह ढेर भ्रष्टाचार के साथ दुर्घटनाओं।

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

+0

मैं समस्या को पुन: पेश नहीं कर सकता। क्या आप इस मुद्दे को प्रदर्शित करने के लिए एक छोटा लेकिन पूरा कार्यक्रम पोस्ट कर सकते हैं? –

+0

मैं 'ReadConsoleW' के वापसी मूल्य की जांच करने और आवश्यकता होने पर' GetLastError' की जांच करने का सुझाव दूंगा। अन्यथा, मेरे पास कोई सुराग नहीं है! –

+0

ने 'ReadConsoleW' के वापसी मूल्य की जांच की, लेकिन प्रत्येक बार वापसी मूल्य nonzero था, इसलिए कोई त्रुटि नहीं। इसके अलावा जब यह ढेर भ्रष्टाचार के साथ दुर्घटनाग्रस्त हो जाता है, तो डीबगर प्रोग्राम के अंत में होता है। – Josh

उत्तर

7

जहां तक ​​मैं कह सकता हूं, यह विंडोज़ में एक बग है।

#include <windows.h> 
#include <crtdbg.h> 

int wmain(int argc, wchar_t *argv[]) 
{ 
    DWORD dwNumRead; 
    wchar_t cBuf[2]; 

    cBuf[0] = cBuf[1] = 65535; 

    HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE); 
    SetConsoleMode(hStdIn, 0); 

    while (true) 
    { 
     _ASSERT(ReadConsoleW(hStdIn, &cBuf[0], 1, &dwNumRead, NULL)); 
     _ASSERT(dwNumRead == 1); 
     _ASSERT(cBuf[1] == 65535); 
     Sleep(5000); 
    } 
} 

नींद यह थोड़ा आसान मुद्दा है, जो जब भी एक से अधिक चरित्र बार जब आप ReadConsoleW फोन पर इंतज़ार कर रहा है तब होता है को गति प्रदान करने में आता है: यहाँ एक से थोड़ा सरल कार्यक्रम है कि समस्या को दर्शाता है है।

प्रासंगिक दावा विफल होने पर cBuf[1] की सामग्री को देखते हुए, ऐसा प्रतीत होता है कि ReadConsoleW बफर के अंत में एक अतिरिक्त बाइट लिख रहा है।

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

+1

दिलचस्प। बस उत्सुक, अगर मैं नींद समारोह को हटा देता हूं, तो मैं इसे ब्रेक पॉइंट ट्रिगर करने के लिए नहीं मिल सकता? यह 5 सेकंड के लिए क्या सो रहा है? – Josh

+1

नींद के बिना, आप एक समय में एक से अधिक पढ़ने के लिए पर्याप्त रूप से कुंजी को हिट करने में सक्षम होने की संभावना नहीं है, हालांकि कट-एंड-पेस्ट का उपयोग करना अभी भी काम कर सकता है। (Putwchar और wprintf की वजह से आपका मूल कोड लूप के लिए थोड़ा धीमा था इसलिए नींद आवश्यक नहीं थी।) –

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